Co nowego w języku C# 12
Język C# 12 zawiera następujące nowe funkcje. Możesz wypróbować te funkcje przy użyciu najnowszej wersji Visual Studio 2022 lub zestawu SDK platformy .NET 8.
podstawowe konstruktory — wprowadzone w programie Visual Studio 2022 w wersji 17.6 (wersja zapoznawcza 2).
Wyrażenia kolekcji — wprowadzone w programie Visual Studio 2022 w wersji 17.7 (wersja zapoznawcza 5).
tablic wbudowanych — wprowadzono w programie Visual Studio 2022 w wersji 17.7 (wersja zapoznawcza 3).
Opcjonalne parametry w wyrażeniach lambda — wprowadzono w programie Visual Studio 2022 w wersji 17.5 (wersja zapoznawcza 2).
ref readonly
parametrów — wprowadzono w programie Visual Studio 2022 w wersji 17.8 (wersja zapoznawcza 2).alias dowolnego typu — wprowadzono w programie Visual Studio 2022 w wersji 17.6 (wersja zapoznawcza 3).
Atrybut eksperymentalny - wprowadzony w programie Visual Studio 2022 wersja 17.7 wersja zapoznawcza 3.
Interceptors - Funkcja wersji zapoznawczej wprowadzona w programie Visual Studio 2022 w wersji 17.7 wersja zapoznawcza 3.
Język C# 12 jest obsługiwany w .NET 8. Aby uzyskać więcej informacji, zobacz wersjonowanie języka C#.
Najnowszą wersję zestawu SDK platformy .NET 8 można pobrać ze strony pobierania .NET . Możesz również pobrać Visual Studio 2022, który zawiera zestaw SDK platformy .NET 8.
Notatka
Interesuje nas Twoja opinia na temat tych funkcji. Jeśli znajdziesz problemy z dowolną z tych nowych funkcji, utwórz nowe zgłoszenie w repozytorium dotnet/roslyn.
Konstruktory pierwotne
Teraz można tworzyć konstruktory podstawowe w dowolnych class
i struct
. Konstruktory podstawowe nie są już ograniczone do typów record
. Podstawowe parametry konstruktora są w zakresie całej treści klasy. Aby upewnić się, że wszystkie podstawowe parametry konstruktora są zdecydowanie przypisane, wszystkie jawnie zadeklarowane konstruktory muszą wywołać konstruktor podstawowy przy użyciu składni this()
. Dodanie konstruktora podstawowego do class
uniemożliwia kompilatorowi deklarowanie niejawnego konstruktora bez parametrów. W struct
niejawny konstruktor bez parametrów inicjuje wszystkie pola, w tym podstawowe parametry konstruktora do wzorca 0-bitowego.
Kompilator generuje właściwości publiczne tylko dla podstawowych parametrów konstruktora i tylko w typach record
, record class
lub record struct
. Nierekordowe klasy i struktury mogą nie zawsze chcieć tego zachowania dla podstawowych parametrów konstruktora.
Więcej informacji na temat konstruktorów podstawowych można dowiedzieć się w samouczku dotyczącym eksplorowania konstruktorów podstawowych i w artykule dotyczącym konstruktorów wystąpień .
Wyrażenia dotyczące kolekcji
Wyrażenia kolekcji wprowadzają nową zwięzłą składnię w celu utworzenia typowych wartości kolekcji. Możliwe jest osadzenie innych kolekcji w tych wartościach przy użyciu operatora spread, elementu ..e
.
Można utworzyć kilka typów przypominających kolekcje bez konieczności korzystania z BCL. Są to następujące typy:
- Typy tablic, takie jak
int[]
. - System.Span<T> i System.ReadOnlySpan<T>.
- Typy obsługujące inicjatory kolekcji, takie jak System.Collections.Generic.List<T>.
W poniższych przykładach pokazano użycie wyrażeń kolekcji:
// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Create a list:
List<string> b = ["one", "two", "three"];
// Create a span
Span<char> c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// Create a jagged 2D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
// Create a jagged 2D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];
Element rozszerzenia , ..e
w wyrażeniu zbioru dodaje wszystkie elementy tego wyrażenia. Argument powinien być typem kolekcji. W poniższych przykładach pokazano, jak działa element spread:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [.. row0, .. row1, .. row2];
foreach (var element in single)
{
Console.Write($"{element}, ");
}
// output:
// 1, 2, 3, 4, 5, 6, 7, 8, 9,
Element spread oblicza każdy element wyrażenia wyliczenia. Każdy element jest uwzględniony w kolekcji danych wyjściowych.
Możesz używać wyrażeń kolekcji w dowolnym miejscu, w którym potrzebujesz kolekcji elementów. Mogą określić początkową wartość kolekcji lub przekazać jako argumenty do metod, które przyjmują typy kolekcji. Więcej informacji na temat wyrażeń kolekcji można znaleźć w artykule referencyjnym dotyczącym języka na temat wyrażeń kolekcji lub w specyfikacji funkcji .
parametry ref readonly
Język C# dodał parametry in
jako sposób przekazywania odwołań do odczytu.
in
parametry zezwalają zarówno na zmienne, jak i wartości, i mogą być używane bez adnotacji argumentów.
Dodanie parametrów ref readonly
zapewnia większą przejrzystość dla interfejsów API, które mogą używać parametrów ref
lub parametrów in
:
- Interfejsy API utworzone przed wprowadzeniem
in
mogą używaćref
, mimo że argument nie jest modyfikowany. Te interfejsy API można zaktualizować przy użyciuref readonly
. Nie będzie to zmiana powodująca niezgodność dla wywołań, tak jak gdyby parametrref
został zmieniony nain
. Przykładem jest System.Runtime.InteropServices.Marshal.QueryInterface. - API, które przyjmują parametr
in
, ale logicznie wymagają zmiennej. Wyrażenie wartości nie działa. Przykładem jest System.ReadOnlySpan<T>.ReadOnlySpan<T>(T). - Interfejsy API, które używają
ref
, ponieważ wymagają zmiennej, ale nie zmieniają tej zmiennej. Przykładem jest System.Runtime.CompilerServices.Unsafe.IsNullRef.
Aby dowiedzieć się więcej na temat parametrów ref readonly
, zobacz artykuł dotyczący modyfikatorów parametrów w dokumentacji językowej lub specyfikację cech ref readonly parametrów.
Domyślne parametry lambda
Teraz można zdefiniować wartości domyślne dla parametrów w wyrażeniach lambda. Składnia i reguły są takie same jak dodawanie wartości domyślnych argumentów do dowolnej metody lub funkcji lokalnej.
Więcej informacji na temat parametrów domyślnych w wyrażeniach lambda można znaleźć w artykule dotyczącym wyrażeń lambda .
Alias dowolnego typu
Możesz użyć dyrektywy aliasu using
do aliasowania dowolnego typu, nie tylko nazwanych typów. Oznacza to, że można tworzyć semantyczne aliasy dla krotek, tablic, wskaźników lub innych niebezpiecznych typów danych. Aby uzyskać więcej informacji, zobacz specyfikację funkcji . Aby zapoznać się z przykładowym przewodnikiem refaktoryzacji, zobacz Refaktoryzacja kodu przy użyciu aliasu dowolnego typu w blogu platformy .NET.
Tablice w linii
Tablice inline są używane przez zespół środowiska uruchomieniowego i innych autorów bibliotek w celu zwiększenia wydajności twoich aplikacji. Tablice inline umożliwiają deweloperowi utworzenie tablicy o stałym rozmiarze w typie struct
. Struktura z wbudowanym buforem powinna zapewniać charakterystykę wydajności podobną do niebezpiecznego bufora o stałym rozmiarze. Prawdopodobnie nie będziesz deklarować własnych tablic wbudowanych, ale używasz ich automatycznie, gdy są udostępniane jako obiekty System.Span<T> lub System.ReadOnlySpan<T> z interfejsów API środowiska uruchomieniowego.
tablicy wbudowanej jest zadeklarowana podobnie do następującej struct
:
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
Są one używane jak każda inna tablica:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
Różnica polega na tym, że kompilator może korzystać ze znanych informacji o tablicy inline. Prawdopodobnie konsumujesz tablice wbudowane tak, jak każdą inną tablicę. Aby uzyskać więcej informacji na temat deklarowania tablic wbudowanych, zobacz dokumentację języka dotyczącą typów struct
.
Atrybut eksperymentalny
Typy, metody lub zestawy można oznaczyć za pomocą System.Diagnostics.CodeAnalysis.ExperimentalAttribute, aby wskazać funkcję eksperymentalną. Kompilator wyświetla ostrzeżenie, jeśli uzyskujesz dostęp do metody lub typu oznaczonego adnotacją ExperimentalAttribute. Wszystkie typy zawarte w zestawie oznaczonym atrybutem Experimental
są eksperymentalne. Więcej informacji można znaleźć w artykule dotyczącym atrybutów ogólnych odczytanych przez kompilatorlub specyfikacji funkcji .
Avicode
Ostrzeżenie
Interceptors to funkcja eksperymentalna dostępna w trybie podglądu w języku C# 12. W przyszłych wydaniach ta funkcja może ulec zmianom powodującym niezgodność lub zostać usunięta. W związku z tym nie jest zalecane w przypadku aplikacji produkcyjnych ani wydanych.
Aby można było używać interceptorów, projekt użytkownika musi określić właściwość <InterceptorsPreviewNamespaces>
. Jest to lista przestrzeni nazw, które mogą zawierać przechwytniki.
Na przykład: <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>
Przechwytywacz to metoda, która może deklaratywnie zastąpić wywołanie metody możliwej do przechwycenia wywołaniem jej samej podczas kompilacji. To podstawienie następuje poprzez to, że przechwytujący deklaruje lokalizacje źródłowe przechwytywanych wywołań. Przechwytniki zapewniają ograniczoną możliwość zmiany semantyki istniejącego kodu przez dodanie nowego kodu do kompilacji, na przykład w generatorze źródłowym.
Używasz interceptora jako części generatora źródłowego do modyfikowania, a nie dodawania kodu do istniejącej kompilacji źródłowej. Generator źródła zastępuje wywołania przechwytywalnej metody wywołaniem metody przechwytującej .
Jeśli interesuje Cię eksperymentowanie z przechwytywaczami, możesz dowiedzieć się więcej, czytając specyfikację funkcji . Jeśli używasz tej funkcji, pamiętaj, aby zachować aktualną każdą zmianę specyfikacji funkcji dla tej funkcji eksperymentalnej. Jeśli funkcja zostanie sfinalizowana, dodamy więcej wskazówek dotyczących tej witryny.