Delen via


Niet-getrainde typeparameteraantekeningen

Notitie

Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.

Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de notities van de Language Design Meeting (LDM) .

Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.

Kampioenprobleem: https://github.com/dotnet/csharplang/issues/3297

Samenvatting

Sta niet-nullable-annotaties toe voor typeparameters die niet zijn beperkt tot waardetypen of referentietypen: T?.

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

aantekening ?

In C#8 konden ? aantekeningen alleen worden toegepast op typeparameters die expliciet zijn beperkt tot waardetypen of verwijzingstypen. In C#9 kunnen ? aantekeningen worden toegepast op elke typeparameter, ongeacht de beperkingen.

Tenzij een typeparameter expliciet is beperkt tot waardetypen, kunnen aantekeningen alleen worden toegepast binnen een #nullable enable context.

Als een typeparameter T wordt vervangen door een verwijzingstype, T? een null-exemplaar van dat verwijzingstype vertegenwoordigt.

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

Als T wordt vervangen door een waardetype, vertegenwoordigt T? een exemplaar van T.

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

Als T wordt vervangen door een geannoteerd type U?, vertegenwoordigt T? het geannoteerde type U? in plaats van U??.

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

Als T wordt vervangen door een type U, vertegenwoordigt T?U?, zelfs binnen een #nullable disable context.

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

Voor retourwaarden is T? gelijk aan [MaybeNull]T; voor argumentwaarden is T? gelijk aan [AllowNull]T. De gelijkwaardigheid is belangrijk bij het overschrijven of implementeren van interfaces van een assembly die is gecompileerd met C#8.

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 beperking

Voor compatibiliteit met bestaande code waarbij overschreven en expliciet geïmplementeerde algemene methoden geen expliciete beperkingsclausules konden bevatten, wordt T? in een overschreven of expliciet geïmplementeerde methode behandeld als Nullable<T> waarbij T een waardetype is.

Om aantekeningen toe te staan voor typeparameters die zijn beperkt tot referentietypen, maakt C#8 het mogelijk om expliciete where T : class- en where T : struct-beperkingen toe te passen op de overschreven of expliciet geïmplementeerde 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 { }
}

Als u aantekeningen wilt toestaan voor typeparameters die niet zijn beperkt tot verwijzingstypen of waardetypen, staat C#9 een nieuwe where T : default beperking toe.

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 { }
}

Het is een vergissing om een default beperking te gebruiken anders dan bij een methode-override of expliciete implementatie. Het is een fout bij het gebruik van een default beperking wanneer de overeenkomstige typeparameter in de overschreven methode of interfacemethode wordt beperkt tot een verwijzingstype of waardetype.

Ontwerpbijeenkomsten