Как возможно поведение 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?

Ответы на вопрос(3)

Ваш ответ на вопрос