Возьмите следующий общий метод:
public static T Get<T>(T value)
{
return value;
}
Если мы называем это как Get<string>(s)
, возврат не обнуляемый, и если мы делаем Get<string?>(s)
, это обнуляемый.
Однако, если вы вызываете его с универсальным аргументом, подобным Get<T>(x)
и T
не разрешенным, например, это универсальный аргумент для вашего универсального класса, как показано ниже ...
class MyClass<T>
{
void Method(T x)
{
var result = Get<T>(x);
// is result nullable or non-nullable? It depends on T
}
}
Здесь компилятор не знает, будет ли он в конечном итоге вызываться с типом NULL или NULL.
Существует новое ограничение типа, которое мы можем использовать для сигнализации, который T
не может быть нулевым:
public static T Get<T>(T value) where T: notnull
{
return value;
}
Однако там, где нет T
ограничений и все еще открыто, обнуляемость неизвестна.
Если эти неизвестные были обработаны как обнуляемые, вы можете написать следующий код:
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;
}
}
В случае, если T
не было обнуляемым, мы должны были получить предупреждение. Таким образом, с неизвестными типами обнуляемости мы хотим получать предупреждения при разыменовании, а также предупреждения о возможном назначении null
.