Почему Nullable <T>считается типом значения? - PullRequest
14 голосов
/ 09 января 2010

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

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

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

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

Ответы [ 4 ]

29 голосов
/ 09 января 2010

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

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

    int? x = 2;
    object y = x;
    

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

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

12 голосов
/ 09 января 2010

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

Кроме того, все операторы исключены из обычных типов для непосредственной работы с обнуляемыми типами.

1 голос
/ 30 ноября 2010

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

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

Nullable<T> дает нам возможность сказать «это не имеет значащего значения», и в этом смысле он может иметь ту же семантику, что и нулевая ссылка, но это не похоже на ссылку любым другим способом. Когда ноль, то это ничтожность - это просто «нет значащего значения», ноль - не «не относится ни к чему», а когда не ноль, оно содержит значение, не ссылаясь на него.

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

1 голос
/ 09 января 2010

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

...