Neuerungen in C# 11

Die folgenden Features wurden C# 11 hinzugefügt:

C# 11 wird in .NET 7 unterstützt. Weitere Informationen finden Sie unter C#-Sprachversionsverwaltung.

Sie können das neueste .NET 7 SDK über die .NET-Downloadseite herunterladen. Sie können auch die Version Visual Studio 2022 herunterladen, die das .NET SDK 7 enthält.

Hinweis

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.

Generische Attribute

Sie können eine generische Klasse deklarieren, deren Basisklasse System.Attribute ist. Dieses Feature bietet eine praktischere Syntax für Attribute, die einen System.Type-Parameter erfordern. Zuvor müssten Sie ein Attribut erstellen, das als Konstruktorparameter Type akzeptiert:

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

   public Type ParamType { get; }
}

Um das Attribut anzuwenden, verwenden Sie den Operator typeof:

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

Mit dieser neuen Funktion können Sie stattdessen ein generisches Attribut erstellen:

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

Geben Sie dann den Typparameter an, um das Attribut zu verwenden:

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

Wenn Sie das Attribut anwenden, müssen Sie alle Typparameter angeben. Anders gesagt: Der generische Typ muss vollständig konstruiert werden. Im obigen Beispiel können die leeren Klammern (( und )) weggelassen werden, da das Attribut keine Argumente enthält.

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

Die Typargumente müssen die gleichen Einschränkungen wie der Operator typeof erfüllen. Typen, die Metadatenanmerkungen erfordern, sind nicht zulässig. Die folgenden Typen beispielsweise sind als Typparameter nicht zulässig:

  • dynamic
  • string? (oder nullwertfähige Verweistypen)
  • (int X, int Y) (oder andere Tupeltypen mit C#-Tupelsyntax).

Diese Typen werden nicht direkt in Metadaten dargestellt. Sie enthalten Anmerkungen, die den Typ beschreiben. In allen Fällen können Sie stattdessen den zugrunde liegenden Typ verwenden:

  • object für dynamic.
  • string anstelle von string?.
  • ValueTuple<int, int> anstelle von (int X, int Y).

Unterstützung generischer Mathematik

Es gibt mehrere Sprachfeatures, die die generische Mathematik unterstützen:

  • static virtual-Member in Schnittstellen
  • Benutzerdefinierte checked-Operatoren
  • Gelockerte Schiebeoperatoren
  • Operator für vorzeichenlose Rechtsverschiebung

Sie können static abstract- oder static virtual-Member in Schnittstellen hinzufügen, um Schnittstellen zu definieren, die überladbare Operatoren, andere statische Member und statische Eigenschaften enthalten. Das primäre Szenario für dieses Feature ist die Verwendung mathematischer Operatoren in generischen Typen. Beispielsweise können Sie die System.IAdditionOperators<TSelf, TOther, TResult>-Schnittstelle in einem Typ implementieren, der operator + implementiert. Andere Schnittstellen definieren andere mathematische Operationen oder genau definierte Werte. Weitere Informationen zur neuen Syntax finden Sie im Artikel zu Schnittstellen. Schnittstellen, die static virtual-Methoden enthalten, sind in der Regel generische Schnittstellen. Darüber hinaus deklarieren die meisten die Einschränkung, dass der Typparameter die deklarierte Schnittstelle implementiert.

Im Tutorial Erkunden statischer abstrakter Schnittstellenmember () oder dem Blogbeitrag Preview features in .NET 6 – generic math erfahren Sie mehr über das Feature und können es ausprobieren.

Durch die generische Mathematik entstehen weitere Anforderungen an die Sprache.

  • Operator für vorzeichenlose Rechtsverschiebung: Um vor C# 11 eine vorzeichenlose Rechtsverschiebung zu erzwingen, mussten Sie jede ganze Zahl mit Vorzeichen in eine ganze Zahl ohne Vorzeichen umwandeln, die Verschiebung durchführen und das Ergebnis dann wieder zurück in eine ganze Zahl mit Vorzeichen umwandeln. Ab C# 11 können Sie >>> nutzen, den Operator für die vorzeichenlose Verschiebung.
  • Anforderungen des gelockerten Schiebeoperators: C# 11 entfernt die Anforderung, dass der zweite Operand int oder implizit konvertierbar in int sein muss. Durch diese Änderung können Typen verwendet werden, die generische mathematische Schnittstellen implementieren.
  • Benutzerdefinierte checked- und unchecked-Operatoren: Entwickler*innen können jetzt die arithmetischen Operatoren checked und unchecked definieren. Der Compiler generiert Aufrufe der richtigen Variante basierend auf dem aktuellen Kontext. Weitere Informationen zu checked-Operatoren finden Sie im Artikel Arithmetische Operatoren.

Numerische IntPtr- und UIntPtr-Typen

Die nint-und nuint-Typen dienen jetzt als Alias für System.IntPtr bzw. System.UIntPtr.

Zeilenvorschübe in Zeichenfolgeninterpolationen

Der Text innerhalb der Zeichen { und } für eine Zeichenfolgeninterpolation darf jetzt mehrere Zeilen umfassen. Der Text zwischen den Markern { und } wird als C# geparst. Alle älteren C#-Befehle, einschließlich Zeilenvorschub, sind weiterhin zulässig. Dieses Feature erleichtert das Lesen von Zeichenfolgeninterpolationen, die längere C#-Ausdrücke verwenden, z. B. switch-Ausdrücke zum Musterabgleich oder LINQ-Abfragen.

Im Artikel Zeichenfolgeninterpolationen in der Sprachreferenz erfahren Sie mehr über das neue Zeilenvorschubfeature.

Listenmuster

Listenmuster erweitern den Musterabgleich und ermöglichen den Abgleich von Elementsequenzen in einer Liste oder einem Array. Ein Beispiel: sequence is [1, 2, 3] ist true, wenn sequence ein Array oder eine Liste mit drei Integerwerten (1, 2 und 3) ist. Sie können Elemente mit beliebigen Mustern abgleichen, einschließlich Konstanten, Typen, Eigenschaften und relationalen Mustern. Das Ausschussmuster (_) stimmt mit einem beliebigen einzelnen Element überein, und das neue Bereichsmuster (..) stimmt mit jeder Sequenz aus null oder mehr Elementen überein.

Weitere Informationen zu Listenmustern finden Sie im Artikel zum Musterabgleich in der Sprachreferenz.

Verbesserte Methodengruppenkonvertierung zu Delegaten

Der C#-Standard für Methodengruppenkonvertierungen enthält jetzt das folgende Element:

  • Die Konvertierung ist zulässig (aber nicht erforderlich), um eine vorhandene Delegatinstanz zu verwenden, die bereits diese Verweise enthält.

Frühere Versionen des Standards verhinderten, dass der Compiler das für eine Methodengruppenkonvertierung erstellte Delegatobjekt erneut verwendete. Der C# 11-Compiler speichert das aus einer Methodengruppenkonvertierung erstellte Delegatobjekt zwischen und verwendet dieses einzelne Delegatobjekt. Dieses Feature war zuerst in Visual Studio 2022 Version 17.2 als Previewfunktion und in .NET 7 Preview 2 verfügbar.

Unformatierte Zeichenfolgenliterale

Unformatierte Zeichenfolgenliterale sind ein neues Format für Zeichenfolgenliterale. Unformatierte Zeichenfolgenliterale können beliebigen Text enthalten, einschließlich Leerzeichen, Zeilenvorschubzeichen, eingebetteten Anführungszeichen und anderen Sonderzeichen, ohne dass Escapesequenzen erforderlich sind. Ein unformatiertes Zeichenfolgenliteral beginnt mit mindestens drei doppelten geraden Anführungszeichen oben ("""). Es endet mit der gleichen Anzahl von doppelten Anführungszeichen. In der Regel verwendet ein unformatiertes Zeichenfolgenliteral drei doppelte Anführungszeichen in einer einzelnen Zeile, um die Zeichenfolge zu starten, und drei doppelte Anführungszeichen in einer separaten Zeile, um die Zeichenfolge zu beenden. Die Zeilenvorschübe nach dem öffnenden und vor dem schließenden Anführungszeichen gehören nicht zum endgültigen Inhalt:

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.
    """;

Alle Leerzeichen links von den schließenden doppelten Anführungszeichen werden aus dem Zeichenfolgenliteral entfernt. Unformatierte Zeichenfolgenliterale können mit Zeichenfolgeninterpolation kombiniert werden, um Klammern in den Ausgabetext einzuschließen. Mehrere $-Zeichen geben an, wie viele aufeinander folgende Klammern die Interpolation starten und beenden:

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

Im obigen Beispiel ist angegeben, dass zwei Klammern eine Interpolation starten und beenden. Das dritte Paar aus öffnender und schließender Klammer ist in der Ausgabezeichenfolge enthalten.

Mehr über unformatierte Zeichenfolgenliterale erfahren Sie im Artikel zu Zeichenfolgen im Programmierleitfaden und in den Artikeln zu Zeichenfolgenliteralen und interpolierten Zeichenfolgen in der Sprachreferenz.

Automatische Standardstrukturen

Der C# 11-Compiler stellt sicher, dass alle Felder eines struct-Typs im Rahmen der Ausführung eines Konstruktors mit ihrem Standardwert initialisiert werden. Diese Änderung bedeutet, dass jedes Feld oder jede Auto-Eigenschaft, das bzw. die nicht von einem Konstruktor initialisiert wird, automatisch vom Compiler initialisiert wird. Strukturen, bei denen der Konstruktor nicht definitiv alle Felder zuweist, werden jetzt kompiliert, und alle Felder, die nicht explizit initialisiert wurden, werden auf ihren Standardwert festgelegt. Weitere Informationen dazu, wie sich diese Änderung auf die Strukturinitialisierung auswirkt, finden Sie im Artikel über Strukturen.

Musterabgleich Span<char> oder ReadOnlySpan<char> für eine Konstante string

Sie konnten mithilfe des Musterabgleichs für mehrere Releases testen, ob ein string über einen bestimmten konstanten Wert verfügte. Jetzt können Sie diese musterabgleichende Logik auch für Variablen verwenden, die Span<char> oder ReadOnlySpan<char> sind.

Erweiterter nameof-Bereich

Typparameternamen und Parameternamen befinden sich jetzt im Bereich, wenn sie in einem nameof-Ausdruck in einer Attributdeklaration für diese Methode verwendet werden. Dieses Feature bedeutet, dass Sie den nameof-Operator verwenden können, um den Namen eines Methodenparameters in einem Attribut für die Methode oder die Parameterdeklaration anzugeben. Dieses Feature ist vor allem nützlich, um Attribute für die Nullable-Analyse hinzuzufügen.

UTF-8-Zeichenfolgenliterale

Sie können das u8-Suffix für ein Zeichenfolgenliteral angeben, um die UTF-8-Zeichencodierung anzugeben. Wenn Ihre Anwendung UTF-8-Zeichenfolgen benötigt, können Sie für HTTP-Zeichenfolgenkonstanten oder ähnliche Textprotokolle dieses Feature verwenden, um die Erstellung von UTF-8-Zeichenfolgen zu vereinfachen.

Weitere Informationen zu UTF-8-Zeichenfolgenliteralen finden Sie im entsprechenden Abschnitt des Artikels zu integrierten Verweistypen.

Erforderliche Member

Sie können den required-Modifizierer zu Eigenschaften und Feldern hinzufügen, um bei Konstruktoren und Aufrufern das Initialisieren dieser Werte zu erzwingen. System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute kann Konstruktoren hinzugefügt werden, um den Compiler darüber zu informieren, dass ein Konstruktor alle erforderlichen Member initialisiert.

Weitere Informationen zu erforderlichen Membern finden Sie im Abschnitt Nur „init“ des Artikels über Eigenschaften.

ref-Typen und ref scoped-Variablen

Sie können ref-Felder in ref struct deklarieren. Dabei werden Typen wie System.Span<T> ohne spezielle Attribute oder ausgeblendete interne Typen unterstützt.

Sie können den scoped-Modifizierer einer ref-Deklaration hinzufügen. Dadurch wird der Escapebereich des Verweises beschränkt.

Dateilokale Typen

Ab C# 11 können Sie den file-Zugriffsmodifizierer verwenden, um einen Typ zu erstellen, dessen Sichtbarkeit auf die Quelldatei festgelegt ist, in der er deklariert ist. Dieses Feature hilft Autor*innen des Quell-Generators dabei, Namenskonflikte zu vermeiden. Weitere Informationen zu diesem Feature finden Sie im Artikel file (C#-Referenz) in der Sprachreferenz.

Siehe auch