Почему Nullable <T> считается типом значения?

Вы когда-нибудь пытались использовать метод Convert.ChangeType() для преобразования значения в тип Nullable<T>? Неловко, он будет бросать InvalidCastException, говоря: "Объект Null не может быть преобразован в тип значения".

Попробуйте запустить это в ближайшем окне: ?System.Convert.ChangeType(null, typeof(int?))

По какой-то непонятной причине Nullables рассматриваются как типы значений. Например, typeof(int?).IsValueType возвращает true.

Для меня, поскольку Nullable<T> accept null, это тип класса, а не тип значения. Кто-нибудь знает, почему это было бы реализовано по-другому?

Ответ 1

System.Nullable<T> является технически структурой, поэтому тип значения (значение null для Nullable<T> не совсем то же самое, что и нулевая ссылка. Это логический флаг, который обозначает отсутствие значения. ) Тем не менее, он обрабатывается специально по времени выполнения, и это делает его неудобным типом значения. Во-первых, он не удовлетворяет ограничению типа where T : struct (он не удовлетворяет where T : class, для чего он стоит). Во-вторых, он демонстрирует интересное поведение в боксе. Бокс a Nullable<T> приведет к:

  • A null, если значение null.
  • Значение в ячейке базового типа, если оно действительно содержит значение. То есть в утверждениях:

    int? x = 2;
    object y = x;
    

    y не помещается в коробку Nullable<int>. Это просто в коробке int. Вы можете удалить все бокс-значения типа T до Nullable<T>T, конечно). Отбрасывание ссылки null на Nullable<T> приводит к значению null (как и следовало ожидать).

Эта специальная обработка по времени выполнения делает типы с нулевым значением более похожими на способ null работает в ссылочных типах.

Ответ 2

Nullable<T> - тип значения (это структура, см. в документации MSDN), но есть неявное преобразование из null до Nullable<T> без значения (x.HasValue == false). Существует также неявное преобразование значений типа T в значения типа Nullable<T>.

Кроме того, все операторы снимаются с обычных типов, чтобы работать непосредственно с типами с возможностью NULL.

Ответ 3

Nullable<T> реализуется как struct и structs являются типами значений.

Ответ 4

Я просто увидел этот вопрос в списке связанных вопросов в Почему Nullable <T> является структурой?, и я думаю, что мой ответ там также применим и здесь. Вся точка Nullable<T> должна действовать как тип значения во всех отношениях, за исключением способности принимать нулевое значение.

Нуль нулевой ссылки можно рассматривать двумя способами. Во-первых, он не ссылается ни на что, другой - на то, что он не имеет значимой ценности. Эти вещи - это почти два разных способа сказать одно и то же, но они имеют разные применения.

Nullable<T> дает нам возможность сказать, что "это не имеет значимого значения", и в той мере, в какой оно может иметь ту же семантику, что и нулевая ссылка, но она не похожа на ссылку каким-либо другим способом. Когда null это nullity является чисто, что "no valueful value" null - not "не ссылается ни на что", и когда он не имеет значения null, он удерживает значение, не ссылаясь на него.

(Aaronaught утверждает, что это означает, что Nullable не может содержать null, в то время как я не согласен, потому что на уровне, на котором он использует его, может иметь семантический нуль, его смысл стоит рассмотреть в том, что даже когда "null" является Nullable отличается от ссылки - действительно, наше несогласие - это вопрос, какой уровень абстракции мы предпочитаем использовать).