Co nowego w języku C# 11

W języku C# 11 dodano następujące funkcje:

Język C# 11 jest obsługiwany na platformie .NET 7. Aby uzyskać więcej informacji, zobacz Przechowywanie wersji języka C#.

Najnowszy zestaw .NET 7 SDK można pobrać ze strony pobierania platformy .NET. Możesz również pobrać program Visual Studio 2022, który zawiera zestaw .NET 7 SDK.

Uwaga

Interesuje nas Twoja opinia na temat tych funkcji. Jeśli znajdziesz problemy z dowolną z tych nowych funkcji, utwórz nowy problem w repozytorium dotnet/roslyn .

Atrybuty ogólne

Można zadeklarować klasę ogólną, której klasa bazowa to System.Attribute. Ta funkcja zapewnia wygodną składnię atrybutów, które wymagają parametru System.Type . Wcześniej należy utworzyć atrybut, który przyjmuje Type jako parametr konstruktora:

// Before C# 11:
public class TypeAttribute : Attribute
{
   public TypeAttribute(Type t) => ParamType = t;

   public Type ParamType { get; }
}

Aby zastosować atrybut, należy użyć typeof operatora :

[TypeAttribute(typeof(string))]
public string Method() => default;

Korzystając z tej nowej funkcji, możesz zamiast tego utworzyć atrybut ogólny:

// C# 11 feature:
public class GenericAttribute<T> : Attribute { }

Następnie określ parametr typu, aby użyć atrybutu:

[GenericAttribute<string>()]
public string Method() => default;

Podczas stosowania atrybutu należy podać wszystkie parametry typu. Innymi słowy, typ ogólny musi być w pełni skonstruowany. W powyższym przykładzie puste nawiasy (( i )) można pominąć, ponieważ atrybut nie ma żadnych argumentów.

public class GenericType<T>
{
   [GenericAttribute<T>()] // Not allowed! generic attributes must be fully constructed types.
   public string Method() => default;
}

Argumenty typu muszą spełniać te same ograniczenia co typeof operator. Typy wymagające adnotacji metadanych nie są dozwolone. Na przykład następujące typy nie są dozwolone jako parametr typu:

  • dynamic
  • string? (lub dowolny typ odwołania dopuszczalny do wartości null)
  • (int X, int Y) (lub innych typów krotki przy użyciu składni krotki języka C#).

Te typy nie są bezpośrednio reprezentowane w metadanych. Zawierają adnotacje opisujące typ. We wszystkich przypadkach można użyć typu bazowego:

  • object dla dynamic.
  • stringstring?zamiast .
  • ValueTuple<int, int>(int X, int Y)zamiast .

Ogólna obsługa matematyczna

Istnieje kilka funkcji językowych, które umożliwiają ogólną obsługę matematyczną:

  • static virtual elementy członkowskie w interfejsach
  • zaznaczone operatory zdefiniowane przez użytkownika
  • swobodne operatory przesunięcia
  • operator niepodpisanego przesunięcia w prawo

Można dodawać static abstract lub static virtual elementy członkowskie w interfejsach, aby definiować interfejsy, które obejmują operatory przeciążalne, inne statyczne elementy członkowskie i właściwości statyczne. Podstawowym scenariuszem tej funkcji jest użycie operatorów matematycznych w typach ogólnych. Na przykład można zaimplementować System.IAdditionOperators<TSelf, TOther, TResult> interfejs w typie, który implementuje operator +element . Inne interfejsy definiują inne operacje matematyczne lub dobrze zdefiniowane wartości. Nową składnię można dowiedzieć się w artykule dotyczącym interfejsów. Interfejsy, które zawierają static virtual metody, są zwykle interfejsami ogólnymi. Ponadto większość deklaruje ograniczenie implementujące zadeklarowany interfejs przez parametr typu.

Możesz dowiedzieć się więcej i wypróbować tę funkcję samodzielnie w samouczku Eksploruj statyczne abstrakcyjne elementy interfejsu lub funkcje w wersji zapoznawczej na platformie .NET 6 — ogólny wpis w blogu matematyczny .

Ogólna matematyka utworzyła inne wymagania dotyczące języka.

  • operator niepodpisanego przesunięcia w prawo: Przed C# 11, aby wymusić niepodpisane przesunięcie w prawo, należy rzutować dowolny typ liczby całkowitej ze znakiem na typ bez znaku, wykonać przesunięcie, a następnie rzutować wynik z powrotem do typu podpisanego. Począwszy od języka C# 11, możesz użyć >>>operatora , bez znaku shift.
  • swobodne wymagania operatora zmiany: C# 11 usuwa wymóg, że drugi operand musi być int lub niejawnie konwertowany na int. Ta zmiana umożliwia używanie typów implementujących ogólne interfejsy matematyczne w tych lokalizacjach.
  • zaznaczone i niezaznaczone operatory zdefiniowane przez użytkownika: deweloperzy mogą teraz definiować checked i unchecked arytmetyczne operatory. Kompilator generuje wywołania poprawnego wariantu na podstawie bieżącego kontekstu. Więcej informacji na temat checked operatorów można przeczytać w artykule na temat operatorów arytmetycznych.

Numeryczne IntPtr i UIntPtr

Wartości nint i nuint są teraz aliasami System.IntPtr i System.UIntPtr, odpowiednio.

Nowe linie w interpolacjach ciągów

Tekst wewnątrz { znaków i } dla interpolacji ciągów może teraz obejmować wiele wierszy. Tekst między { znacznikami i } jest analizowany jako C#. Wszelkie prawne C#, w tym nowe linie, są dozwolone. Ta funkcja ułatwia odczytywanie interpolacji ciągów, które używają dłuższych wyrażeń języka C#, takich jak wyrażenia dopasowania switch wzorca lub zapytania LINQ.

Więcej informacji na temat funkcji newlines można znaleźć w artykule interpolacji ciągów w dokumentacji językowej.

Wzorce listy

Wzorce listy rozszerzają dopasowanie wzorca w celu dopasowania sekwencji elementów na liście lub tablicy. Na przykład jest true to, sequence is [1, 2, 3] gdy sequence jest tablicą lub listą trzech liczb całkowitych (1, 2 i 3). Elementy można dopasować przy użyciu dowolnego wzorca, w tym stałych, typów, właściwości i wzorców relacyjnych. Wzorzec odrzucenia (_) pasuje do dowolnego pojedynczego elementu, a nowy wzorzec zakresu (..) pasuje do dowolnej sekwencji zera lub większej liczby elementów.

Więcej szczegółowych informacji na temat wzorców list można znaleźć w artykule dotyczącym dopasowywania wzorców w dokumentacji językowej.

Ulepszona konwersja grupy metod na delegowanie

Standard języka C# w przypadku konwersji grup metod zawiera teraz następujący element:

  • Konwersja jest dozwolona (ale nie jest wymagana) do użycia istniejącego wystąpienia delegata, które zawiera już te odwołania.

Poprzednie wersje standardu uniemożliwiły kompilatorowi ponowne używanie obiektu delegata utworzonego na potrzeby konwersji grupy metod. Kompilator języka C# 11 buforuje obiekt delegata utworzony na podstawie konwersji grupy metod i ponownie używa tego pojedynczego obiektu delegata. Ta funkcja była po raz pierwszy dostępna w programie Visual Studio 2022 w wersji 17.2 jako funkcja w wersji zapoznawczej i na platformie .NET 7 (wersja zapoznawcza 2).

Nieprzetworzone literały ciągu

Nieprzetworzone literały ciągu to nowy format literałów ciągu. Nieprzetworzone literały ciągu mogą zawierać dowolny tekst, w tym biały znak, nowe wiersze, osadzone cudzysłowy i inne znaki specjalne bez konieczności sekwencji ucieczki. Literał nieprzetworzonego ciągu zaczyna się od co najmniej trzech znaków podwójnego cudzysłowu ("""). Kończy się taką samą liczbą znaków podwójnego cudzysłowu. Zazwyczaj literał nieprzetworzonego ciągu używa trzech podwójnych cudzysłowów w jednym wierszu, aby rozpocząć ciąg, a trzy podwójne cudzysłowy w osobnym wierszu, aby zakończyć ciąg. Nowe linie po cudzysłowie otwierającym i poprzedzającym cudzysłów zamykających nie są uwzględnione w końcowej zawartości:

string longMessage = """
    This is a long message.
    It has several lines.
        Some are indented
                more than others.
    Some should start at the first column.
    Some have "quoted text" in them.
    """;

Wszelkie białe znaki z lewej strony zamykających cudzysłowów zostaną usunięte z literału ciągu. Nieprzetworzone literały ciągu można łączyć z interpolacją ciągów w celu uwzględnienia nawiasów klamrowych w tekście wyjściowym. Wiele $ znaków określa liczbę kolejnych nawiasów klamrowych rozpoczynających i kończących interpolację:

var location = $$"""
   You are at {{{Longitude}}, {{Latitude}}}
   """;

W poprzednim przykładzie określono, że dwa nawiasy klamrowe rozpoczynają się i kończą interpolację. Trzeci powtórzony nawias klamrowy otwierający i zamykający są zawarte w ciągu wyjściowym.

Więcej informacji na temat literałów nieprzetworzonych ciągów można dowiedzieć się w artykule dotyczącym ciągów w przewodniku programowania oraz artykułach referencyjnych języka dotyczących literałów ciągów i ciągów interpolowanych.

Automatycznie domyślna struktura

Kompilator języka C# 11 zapewnia, że wszystkie pola struct typu są inicjowane do ich wartości domyślnej w ramach wykonywania konstruktora. Ta zmiana oznacza, że dowolne pole lub właściwość automatyczna, która nie została zainicjowana przez konstruktora, jest automatycznie inicjowana przez kompilator. Struktury, w których konstruktor nie przypisze teraz wszystkich pól, a wszystkie pola, które nie zostały jawnie zainicjowane, są ustawiane na ich wartość domyślną. Więcej informacji na temat wpływu tej zmiany na inicjowanie struktury można dowiedzieć się w artykule dotyczącym struktur.

Dopasowanie Span<char> wzorca lub ReadOnlySpan<char> na stałe string

Udało Ci się sprawdzić, czy element string miał określoną stałą wartość przy użyciu dopasowania wzorca dla kilku wersji. Teraz możesz użyć tej samej logiki dopasowania wzorca ze zmiennymi, które są Span<char> lub ReadOnlySpan<char>.

Zakres rozszerzonej nazwy

Nazwy parametrów typu i nazwy parametrów są teraz w zakresie, gdy są używane w wyrażeniu nameofw deklaracji atrybutu w tej metodzie. Ta funkcja oznacza, że za pomocą nameof operatora można określić nazwę parametru metody w atrybucie w metodzie lub deklaracji parametru. Ta funkcja jest najczęściej przydatna do dodawania atrybutów do analizy dopuszczanej do wartości null.

Literały ciągu UTF-8

Można określić u8 sufiks literału ciągu, aby określić kodowanie znaków UTF-8. Jeśli aplikacja potrzebuje ciągów UTF-8, dla stałych ciągów HTTP lub podobnych protokołów tekstowych, możesz użyć tej funkcji, aby uprościć tworzenie ciągów UTF-8.

Więcej informacji na temat literałów ciągów UTF-8 można dowiedzieć się w sekcji literału ciągu artykułu na temat wbudowanych typów odwołań.

Wymagane elementy członkowskie

Modyfikator można dodać required do właściwości i pól, aby wymusić konstruktory i obiekty wywołujące w celu zainicjowania tych wartości. Element System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute można dodać do konstruktorów, aby poinformować kompilator, że konstruktor inicjuje wszystkie wymagane elementy członkowskie.

Aby uzyskać więcej informacji na temat wymaganych elementów członkowskich, zobacz sekcję tylko do inicjowania artykułu właściwości.

ref pola i ref scoped zmienne

Możesz zadeklarować ref pola wewnątrz elementu ref struct. Obsługuje to typy, takie jak System.Span<T> bez atrybutów specjalnych lub ukrytych typów wewnętrznych.

Modyfikator można dodać scoped do dowolnej ref deklaracji. Ogranicza to zakres, w którym odwołanie może uciec.

Typy lokalne plików

Począwszy od języka C# 11, można użyć file modyfikatora dostępu, aby utworzyć typ, którego widoczność jest ograniczona do pliku źródłowego, w którym jest zadeklarowany. Ta funkcja pomaga autorom generatora źródeł uniknąć kolizji nazewnictwa. Więcej informacji na temat tej funkcji można znaleźć w artykule dotyczącym typów o zakresie plików w dokumentacji językowej.

Zobacz też