Tome el siguiente método genérico:
public static T Get<T>(T value)
{
return value;
}
Si lo llamamos así Get<string>(s)
, el retorno no es anulable, y si lo hacemos Get<string?>(s)
, es anulable.
Sin embargo, si lo está llamando con un argumento genérico como Get<T>(x)
y T
no se resuelve, por ejemplo, es un argumento genérico para su clase genérica como se muestra a continuación ...
class MyClass<T>
{
void Method(T x)
{
var result = Get<T>(x);
// is result nullable or non-nullable? It depends on T
}
}
Aquí el compilador no sabe si finalmente se llamará con un tipo anulable o no anulable.
Hay una nueva restricción de tipo que podemos usar para señalar que T
no puede ser nula:
public static T Get<T>(T value) where T: notnull
{
return value;
}
Sin embargo, donde T
no está restringido y todavía está abierto, se desconoce la nulabilidad.
Si estas incógnitas se trataran como anulables, podría escribir el siguiente código:
class MyClass<T>
{
void Method(T x)
{
var result = Get<T>(x);
// reassign result to null, cause we we could if unknown was treated as nullable
result = null;
}
}
En el caso de que T
no fuera anulable, deberíamos haber recibido una advertencia. Entonces, con tipos de nulabilidad desconocidos, queremos advertencias al desreferenciar, pero también advertencias para asignar potencialmente null
.