Freigeben über


Nicht eingeschränkte Typparameteranmerkungen

Anmerkung

Dieser Artikel ist eine Featurespezifikation. Die Spezifikation dient als Designdokument für das Feature. Es enthält vorgeschlagene Spezifikationsänderungen sowie Informationen, die während des Entwurfs und der Entwicklung des Features erforderlich sind. Diese Artikel werden veröffentlicht, bis die vorgeschlagenen Spezifikationsänderungen abgeschlossen und in die aktuelle ECMA-Spezifikation aufgenommen werden.

Es kann einige Abweichungen zwischen der Featurespezifikation und der abgeschlossenen Implementierung geben. Diese Unterschiede werden in den entsprechenden Hinweisen zum Language Design Meeting (LDM) erfasst.

Weitere Informationen zum Einführen von Featurespezifikationen in den C#-Sprachstandard finden Sie im Artikel zu den Spezifikationen.

Champion Issue: https://github.com/dotnet/csharplang/issues/3297

Zusammenfassung

Erlaubt Nullbarkeitsanmerkungen für Typparameter, die nicht auf Werttypen oder Verweistypen beschränkt sind: T?.

static T? FirstOrDefault<T>(this IEnumerable<T> collection) { ... }

? Anmerkung

In C#8 konnten ? Anmerkungen nur auf Typparameter angewendet werden, die explizit auf Werttypen oder Verweistypen beschränkt wurden. In C#9 können ?-Anmerkungen ungeachtet von Einschränkungen auf jeden Typparameter angewendet werden.

Sofern kein Typparameter explizit auf Werttypen beschränkt ist, können Anmerkungen nur innerhalb eines #nullable enable Kontexts angewendet werden.

Wenn ein Typparameter T durch einen Verweistyp ersetzt wird, stellt T? eine nullfähige Instanz dieses Verweistyps dar.

var s1 = new string[0].FirstOrDefault();  // string? s1
var s2 = new string?[0].FirstOrDefault(); // string? s2

Wenn T durch einen Werttyp ersetzt wird, stellt T? eine Instanz von Tdar.

var i1 = new int[0].FirstOrDefault();  // int i1
var i2 = new int?[0].FirstOrDefault(); // int? i2

Wenn T durch einen kommentierten Typ U?ersetzt wird, stellt T? den kommentierten Typ U? anstelle von U??dar.

var u1 = new U[0].FirstOrDefault();  // U? u1
var u2 = new U?[0].FirstOrDefault(); // U? u2

Wenn T durch einen Typ Uersetzt wird, stellt T?U?sogar innerhalb eines #nullable disable Kontexts dar.

#nullable disable
var u3 = new U[0].FirstOrDefault();  // U? u3

Bei Rückgabewerten entspricht T?[MaybeNull]T; für Argumentwerte entspricht T?[AllowNull]T. Die Äquivalenz ist wichtig, wenn Schnittstellen aus einer Assembly überschrieben oder implementiert werden, die mit C#8 kompiliert wurde.

public abstract class A
{
    [return: MaybeNull] public abstract T F1<T>();
    public abstract void F2<T>([AllowNull] T t);
}

public class B : A
{
    public override T? F1<T>() where T : default { ... }       // matches A.F1<T>()
    public override void F2<T>(T? t) where T : default { ... } // matches A.F2<T>()
}

default Einschränkung

Aus Gründen der Kompatibilität mit vorhandenem Code, in dem überschriebene und explizit implementierte generische Methoden keine expliziten Einschränkungsklauseln enthalten konnten, wird T? in einer überschriebenen oder explizit implementierten Methode als Nullable<T> behandelt, wobei T ein Werttyp ist.

Um Annotationen für Typparameter, die auf Verweistypen beschränkt sind, zu ermöglichen, erlaubt C#8 explizite where T : class- und where T : struct-Einschränkungen für die überschriebene oder explizit implementierte Methode.

class A1
{
    public virtual void F1<T>(T? t) where T : struct { }
    public virtual void F1<T>(T? t) where T : class { }
}

class B1 : A1
{
    public override void F1<T>(T? t) /*where T : struct*/ { }
    public override void F1<T>(T? t) where T : class { }
}

Um Anmerkungen für Typparameter zuzulassen, die nicht auf Bezugstypen oder Werttypen beschränkt sind, ermöglicht C#9 eine neue where T : default Einschränkung.

class A2
{
    public virtual void F2<T>(T? t) where T : struct { }
    public virtual void F2<T>(T? t) { }
}

class B2 : A2
{
    public override void F2<T>(T? t) /*where T : struct*/ { }
    public override void F2<T>(T? t) where T : default { }
}

Es ist ein Fehler, eine default-Einschränkung anders als bei einer Methodenüberschreibung oder einer expliziten Implementierung zu verwenden. Es ist ein Fehler, eine default-Einschränkung zu verwenden, wenn der entsprechende Typparameter in einer überschriebenen Methode oder Schnittstellenmethode auf einen Referenztyp oder Wertetyp beschränkt ist.

Design-Besprechungen