Хотя C # делает вид, что места хранения типов значений содержат экземпляры типов, полученных из System.ValueType
, что, в свою очередь, происходит от System.Object
, на самом деле это не так. Каждый тип, полученный из System.ValueType
, на самом деле представляет два совершенно разных вида вещей:
- Набор байтов, который (для примитивных типов) представляет данные напрямую или (для не примитивных типов структуры) содержит содержимое всех полей, открытых и закрытых, но не содержит никакой информации о типах.
- Автономный объект кучи, который в дополнение к вышеупомянутому содержит заголовок объекта, тип которого получен из `System.ValueType`.
Места хранения типа значения содержат первое; объекты кучи типа значения содержат второй.
По разным причинам Microsoft решила, что Nullable<T>
должна поддерживать только первое использование. Если вы попытаетесь передать место хранения типа Nullable<T>
в код, который ожидает ссылку на объект кучи, система преобразует элемент в T
, если HasValue
имеет значение true, или просто передаст нулевую ссылку, если HasValue
ложно. Хотя существуют способы создания объекта кучи типа Nullable<T>
, обычные методы преобразования места хранения типа значения в объект кучи никогда не сгенерируют его.
Также обратите внимание, что вызов GetType()
для хранилища значений не будет фактически определять тип хранилища, но вместо этого преобразует содержимое этого хранилища в объект кучи и затем возвращает тип полученного объекта. , Поскольку хранилища типа Nullable<T>
преобразуются либо в экземпляры объекта T
, либо в ноль, ничто в экземпляре объекта не скажет, было ли хранилище, из которого оно получено, Nullable<T>
.