Anotaciones de parámetros de tipo sin restriccionesUnconstrained type parameter annotations

ResumenSummary

Permite anotaciones que aceptan valores NULL para los parámetros de tipo que no están restringidos a tipos de valor o tipos de referencia: T? .Allow nullable annotations for type parameters that are not constrained to value types or reference types: T?.

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

Anotación ?? annotation

En C# 8, las ? anotaciones solo se pueden aplicar a parámetros de tipo que se limitaban explícitamente a tipos de valor o tipos de referencia.In C#8, ? annotations could only be applied to type parameters that were explicitly constrained to value types or reference types. En C# 9, ? las anotaciones se pueden aplicar a cualquier parámetro de tipo, independientemente de las restricciones.In C#9, ? annotations can be applied to any type parameter, regardless of constraints.

A menos que un parámetro de tipo se restrinja explícitamente a los tipos de valor, las anotaciones solo se pueden aplicar dentro de un #nullable enable contexto.Unless a type parameter is explicitly constrained to value types, annotations can only be applied within a #nullable enable context.

Si un parámetro de tipo T se sustituye por un tipo de referencia, T? representa una instancia que acepta valores NULL de ese tipo de referencia.If a type parameter T is substituted with a reference type, then T? represents a nullable instance of that reference type.

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

Si T se sustituye por un tipo de valor, T? representa una instancia de T .If T is substituted with a value type, then T? represents an instance of T.

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

Si T se sustituye por un tipo anotado U? , T? representa el tipo anotado U? en lugar de U?? .If T is substituted with an annotated type U?, then T? represents the annotated type U? rather than U??.

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

Si T se sustituye por un tipo U , T? representa U? , incluso dentro de un #nullable disable contexto.If T is substituted with a type U, then T? represents U?, even within a #nullable disable context.

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

Para los valores devueltos, T? es equivalente a [MaybeNull]T ; para los valores de argumento, T? es equivalente a [AllowNull]T .For return values, T? is equivalent to [MaybeNull]T; for argument values, T? is equivalent to [AllowNull]T. La equivalencia es importante al reemplazar o implementar interfaces de un ensamblado compilado con C# 8.The equivalence is important when overriding or implementing interfaces from an assembly compiled with 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 restriccióndefault constraint

Por compatibilidad con el código existente en el que los métodos genéricos invalidados y implementados explícitamente no pueden incluir cláusulas de restricción explícitas, T? en un método invalidado o implementado explícitamente se trata como Nullable<T> donde T es un tipo de valor.For compatibility with existing code where overridden and explicitly implemented generic methods could not include explicit constraint clauses, T? in an overridden or explicitly implemented method is treated as Nullable<T> where T is a value type.

Para permitir anotaciones para parámetros de tipo restringidos a tipos de referencia, C# 8 permitía where T : class restricciones y explícitas where T : struct en el método invalidado o implementado explícitamente.To allow annotations for type parameters constrained to reference types, C#8 allowed explicit where T : class and where T : struct constraints on the overridden or explicitly implemented method.

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

Para permitir anotaciones para parámetros de tipo que no están restringidos a tipos de referencia o tipos de valor, C# 9 permite una nueva where T : default restricción.To allow annotations for type parameters that are not constrained to reference types or value types, C#9 allows a new where T : default constraint.

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 un error utilizar una default restricción distinta de en una invalidación de método o una implementación explícita.It is an error to use a default constraint other than on a method override or explicit implementation. Es un error utilizar una default restricción cuando el parámetro de tipo correspondiente en el método de interfaz o invalidado está restringido a un tipo de valor o tipo de referencia.It is an error to use a default constraint when the corresponding type parameter in the overridden or interface method is constrained to a reference type or value type.

Design MeetingsDesign meetings