Neuerungen in C# 12
C# 12 enthält die folgenden neuen Features. Sie können diese Features mit der neuesten Visual Studio 2022--Version oder dem .NET 8 SDK-ausprobieren.
Primäre Konstruktoren – Eingeführt in Visual Studio 2022, Version 17.6 Preview 2.
Auflistungsausdrücke – Eingeführt in Visual Studio 2022, Version 17.7 Preview 5.
Inlinearrays – Eingeführt in Visual Studio 2022, Version 17.7 Preview 3.
Optionale Parameter in Lambda-Ausdrücken – Eingeführt in Visual Studio 2022, Version 17.5 Preview 2.
ref readonly
Parameter – Eingeführt in Visual Studio 2022, Version 17.8 Preview 2.Alias für beliebigen Typ – In Visual Studio 2022, Version 17.6, Preview 3 eingeführt.
Experimental-Attribut – Eingeführt in Visual Studio 2022, Version 17.7 Preview 3.
Interceptors - Previewfunktion In Visual Studio 2022, Version 17.7, Preview 3 eingeführt.
C# 12 wird für .NET 8unterstützt. Weitere Informationen finden Sie unter C#-Sprachversionsverwaltung.
Sie können das neueste .NET 8 SDK von der .NET-Downloadseiteherunterladen. Sie können auch Visual Studio 2022-herunterladen, das das .NET 8 SDK enthält.
Anmerkung
Wir interessieren uns für Ihr Feedback zu diesen Features. Wenn Sie bei einem dieser neuen Features auf Probleme stoßen, erstellen Sie ein neues Problem im Repository dotnet/roslyn.
Primäre Konstruktoren
Sie können jetzt in allen class
- und struct
-Elementen primäre Konstruktoren erstellen. Primäre Konstruktoren sind nicht mehr auf record
Typen beschränkt. Parameter für primäre Konstruktoren sind für den gesamten Text der Klasse gültig. Um sicherzustellen, dass alle primären Konstruktorparameter definitiv zugewiesen sind, müssen alle explizit deklarierten Konstruktoren den primären Konstruktor mithilfe this()
Syntax aufrufen. Das Hinzufügen eines primären Konstruktors zu einem class
verhindert, dass der Compiler einen impliziten parameterlosen Konstruktor deklariert. In einem struct
initialisiert der implizite parameterlose Konstruktor alle Felder, einschließlich primärer Konstruktorparameter für das 0-Bit-Muster.
Der Compiler generiert öffentliche Eigenschaften für primäre Konstruktorparameter nur bei record
-Typen, entweder record class
- oder record struct
-Typen. Nichtrecordklassen und -strukturen möchten dieses Verhalten für primäre Konstruktorparameter möglicherweise nicht immer.
Weitere Informationen zu primären Konstruktoren finden Sie im Lernprogramm zum Untersuchen primärer Konstruktoren und im Artikel zu Instanzkonstruktoren.
Sammlungsausdrücke
Sammlungsausdrücke führen eine neue kompakte Syntax ein, um allgemeine Sammlungswerte zu erstellen. Das Eingliedern anderer Auflistungen in diese Werte ist mithilfe eines Spread-Elements ..e
möglich.
Mehrere sammlungsähnliche Typen können erstellt werden, ohne dass externe BCL-Unterstützung erforderlich ist. Diese Typen sind:
- Arraytypen wie
int[]
- System.Span<T> und System.ReadOnlySpan<T>.
- Typen, die Auflistungsinitialisierer unterstützen, z. B. System.Collections.Generic.List<T>
Die folgenden Beispiele zeigen die Verwendung von Auflistungsausdrücken:
// 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];
Das Spread-Element, ..e
in einem Sammlungsausdruck fügt alle Elemente in diesem Ausdruck hinzu. Das Argument muss ein Sammlungstyp sein. Die folgenden Beispiele zeigen, wie das Spread-Element funktioniert:
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,
Das Spread-Element wertet jedes Element des Enumerationsausdrucks aus. Jedes Element ist in der Ausgabeauflistung enthalten.
Sie können Sammlungsausdrücke überall verwenden, wo Sie eine Sammlung von Elementen benötigen. Sie können den Anfangswert für eine Auflistung angeben oder als Argumente an Methoden übergeben werden, die Sammlungstypen verwenden. Weitere Informationen zu Auflistungsausdrücken finden Sie im Sprachreferenzartikel zu Auflistungsausdrücken oder der Featurespezifikation.
ref readonly
Parameter
C# hat in
-Parameter als Möglichkeit zum Übergeben von lesegeschützten Verweisen hinzugefügt. in
Parameter können sowohl Variablen als auch Werte zulassen und ohne Annotationen bei Argumenten verwendet werden.
Das Hinzufügen von ref readonly
Parametern ermöglicht mehr Klarheit für APIs, die möglicherweise ref
Parameter oder in
Parameter verwenden:
- APIs, die vor der Einführung von
in
erstellt wurden, könnenref
verwenden, obwohl das Argument nicht geändert wird. Diese APIs können mitref readonly
aktualisiert werden. Für Anrufer ist dies kein Breaking Change, wie es der Fall wäre, wenn derref
-Parameter zuin
geändert würde. Ein Beispiel ist System.Runtime.InteropServices.Marshal.QueryInterface. - APIs, die einen
in
-Parameter verwenden, aber logisch eine Variable erfordern. Ein Wertausdruck funktioniert nicht. Ein Beispiel ist System.ReadOnlySpan<T>.ReadOnlySpan<T>(T). - APIs, die
ref
verwenden, da sie eine Variable erfordern, diese Variable jedoch nicht verändern. Ein Beispiel ist System.Runtime.CompilerServices.Unsafe.IsNullRef.
Weitere Informationen zu ref readonly
-Parametern finden Sie im Artikel über Parametermodifizierer in der Sprachreferenz oder in der Funktionsspezifikation Ref readonly-Parameter.
Standardmäßige Lambdaparameter
Sie können jetzt Standardwerte für Parameter für Lambda-Ausdrücke definieren. Die Syntax und Regeln entsprechen dem Hinzufügen von Standardwerten für Argumente zu einer beliebigen Methode oder lokalen Funktion.
Weitere Informationen zu Standardparametern für Lambda-Ausdrücke finden Sie im Artikel zu Lambda-Ausdrücken.
Alias für beliebigen Typ
Sie können die using
-Aliasdirektive verwenden, um jeden beliebigen Typen als Alias zu verwenden, nicht nur benannte Typen. Dies bedeutet, dass Sie semantische Aliase für Tupeltypen, Arraytypen, Zeigertypen oder andere unsichere Typen erstellen können. Weitere Informationen finden Sie in der Featurespezifikation. Eine exemplarische Vorgehensweise zum Refactoring finden Sie im .NET-Blog-Beitrag Refactor your code using alias any type (Refactoring Ihres Codes mit „Alias für beliebigen Typ“).
Inlinearrays
Inlinearrays werden vom Laufzeitteam und anderen Bibliotheksautoren verwendet, um die Leistung in Ihren Apps zu verbessern. Inlinearrays ermöglichen es einem Entwickler, ein Array fester Größe in einem struct
Typ zu erstellen. Eine Struktur mit einem Inlinepuffer sollte Leistungsmerkmale bereitstellen, die einem unsicheren Puffer mit fester Größe ähneln. Sie deklarieren wahrscheinlich keine eigenen Inlinearrays, verwenden sie jedoch transparent, wenn sie als System.Span<T> oder System.ReadOnlySpan<T> Objekte aus Laufzeit-APIs verfügbar gemacht werden.
Ein Inlinearray wird ähnlich wie das folgende struct
deklariert:
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
Sie verwenden sie wie jedes andere Array:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
Der Unterschied besteht darin, dass der Compiler bekannte Informationen zu einem Inlinearray nutzen kann. Wahrscheinlich verwenden Sie Inline-Arrays genauso wie jedes andere Array. Weitere Informationen zum Deklarieren von Inlinearrays finden Sie in der Sprachreferenz zu struct
-Typen.
Experimentelles Attribut
Typen, Methoden oder Assemblys können mit dem System.Diagnostics.CodeAnalysis.ExperimentalAttribute gekennzeichnet werden, um ein experimentelles Feature anzugeben. Der Compiler gibt eine Warnung aus, wenn Sie auf eine mit ExperimentalAttributeannotierte Methode oder einen Typ zugreifen. Alle Typen, die in einer Assembly enthalten sind, die mit dem attribut Experimental
gekennzeichnet ist, sind experimentell. Weitere Informationen finden Sie im Artikel Vom Compiler gelesene allgemeinene Attribute oder in der Funktionspezifikation.
Interceptors
Warnung
Interceptors sind ein experimentelles Feature, das im Vorschaumodus mit C# 12 verfügbar ist. Das Feature kann in einer zukünftigen Version Breaking Changes unterliegen oder entfernt werden. Daher wird es nicht für Produktions- oder freigegebene Anwendungen empfohlen.
Um Interceptors zu verwenden, muss das Benutzerprojekt die Eigenschaft <InterceptorsPreviewNamespaces>
angeben. Dies ist eine Liste von Namespaces, die Abfangvorrichtungen enthalten dürfen.
Beispiel: <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>
Ein Interceptor ist eine Methode, die einen Aufruf an eine abfangbare Methode zur Kompilierzeit durch einen Aufruf an sich selbst deklarativ ersetzen kann. Diese Ersetzung tritt auf, indem der Interceptor die Quellstandorte der Aufrufe deklariert, die er abfängt. Interceptors bieten eine eingeschränkte Möglichkeit, die Semantik des vorhandenen Codes zu ändern, indem neue Code zu einer Kompilierung hinzugefügt werden, z. B. in einem Quellgenerator.
Ein Interceptor wird als Teil eines Quellgenerators zum Ändern verwendet, anstatt Code zu einer vorhandenen Quellkompilierung hinzuzufügen. Der Quellgenerator ersetzt Aufrufe an eine abfangbare Methode durch einen Aufruf an die Interceptor-Methode.
Wenn Sie mit Interceptors experimentieren möchten, können Sie mehr erfahren, indem Sie die Funktionsspezifikationlesen. Wenn Sie das Feature verwenden, stellen Sie sicher, dass Sie mit allen Änderungen der Featurespezifikation für dieses experimentelle Feature auf dem neuesten Stand bleiben. Wenn die Funktion fertiggestellt ist, fügen wir weitere Anleitungen auf dieser Website hinzu.