Как возможно поведение Nullable <T> в виде упаковки / распаковки?
Раньше сегодня со мной что-то произошло, что заставило меня почесать голову.
Любая переменная типаNullable<T>
может быть назначенnull
, Например:
int? i = null;
Сначала я не мог понять, как это было бы возможно без какого-либо определения неявного преобразования изobject
вNullable<T>
:
public static implicit operator Nullable<T>(object box);
Но приведенный выше оператор явно не существует, как если бы он существовал, то следующее также должно быть допустимым, по крайней мере, во время компиляции (что не так):
int? i = new object();
Тогда я понял, что, возможно,Nullable<T>
Тип может определить неявное преобразование в некоторый произвольный ссылочный тип, который никогда не может быть создан, например:
public abstract class DummyBox
{
private DummyBox()
{ }
}
public struct Nullable<T> where T : struct
{
public static implicit operator Nullable<T>(DummyBox box)
{
if (box == null)
{
return new Nullable<T>();
}
// This should never be possible, as a DummyBox cannot be instantiated.
throw new InvalidCastException();
}
}
Тем не менее, это не объясняет, что произошло со мной дальше: еслиHasValue
свойствоfalse
для любогоNullable<T>
значение, то это значение будет помечено какnull
:
int? i = new int?();
object x = i; // Now x is null.
Кроме того, еслиHasValue
являетсяtrue
, затем значение будет помечено какT
а неT?
:
int? i = 5;
object x = i; // Now x is a boxed int, NOT a boxed Nullable<int>.
Ноэтот кажется, подразумевает, что есть неявное пользовательское преобразование изNullable<T>
вobject
:
public static implicit operator object(Nullable<T> value);
Это явно не тот случай, когдаobject
является базовым классом для всех типов, и определенные пользователем неявные преобразования в / из базовых типов недопустимы (как и должно быть).
Кажется, чтоobject x = i;
следует коробкаi
как и любой другой тип значения, так чтоx.GetType()
даст тот же результат, что иtypeof(int?)
(а не бросатьNullReferenceException
).
Поэтому я немного покопался и, конечно же, оказалось, что это поведение относится кNullable<T>
тип, специально определенный в спецификациях C # и VB.NET и не воспроизводимый в каких-либо пользовательскихstruct
(C #) илиStructure
(VB.NET).
Вот почему я все еще в замешательстве.
Это конкретное поведение при упаковке и распаковке, по-видимому, невозможно реализовать вручную. Это работает только потому, что и C #, и VB.NET уделяют особое вниманиеNullable<T>
тип.
Разве теоретически не возможно, чтобы существовал другой язык на основе CLI, гдеNullable<T>
не получили этого специального лечения? И не будетNullable<T>
типа поэтому выставляюдругое поведение на разных языках?
Как работают C # и VB.NETдостигать это поведение? Это поддерживается CLR? (То есть, позволяет ли CLR типу каким-то образом "переопределять" способ, которым он упакован, даже если C # и VB.NET сами запрещают это?)
Это дажевозможный (в C # или VB.NET), чтобы поставитьNullable<T>
какobject
?