¿Cómo es posible el comportamiento de boxing / unboxing de Nullable <T>?

Hoy se me ocurrió algo que me hizo rascarme la cabeza.

Cualquier variable de tipoNullable<T> puede ser asignado anull. Por ejemplo:

int? i = null;

Al principio no podía ver cómo esto sería posible sin definir de alguna manera una conversión implícita deobject aNullable<T>:

public static implicit operator Nullable<T>(object box);

Pero el operador anterior claramente no existe, como si existiera, entonces lo siguiente también debería ser legal, al menos en tiempo de compilación (que no lo es):

int? i = new object();

Entonces me di cuenta de que tal vez elNullable<T> tipo podría definir una conversión implícita a algún tipo de referencia arbitraria que nunca puede ser instanciada, como esta:

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();
    }
}

Sin embargo, esto no explica lo que se me ocurrió a continuación: si elHasValue la propiedad esfalse para cualquierNullable<T> valor, entonces ese valor se encuadrará comonull:

int? i = new int?();
object x = i; // Now x is null.

Además, siHasValue estrue, entonces el valor será encuadrado como unT preferible aT?:

int? i = 5;
object x = i; // Now x is a boxed int, NOT a boxed Nullable<int>.

Peroesta parece implicar que hay una conversión implícita personalizada deNullable<T> aobject:

public static implicit operator object(Nullable<T> value);

Esto claramente no es el caso comoobject es una clase base para todos los tipos, y las conversiones implícitas definidas por el usuario a / desde los tipos base son ilegales (también deberían serlo).

Parece queobject x = i; debe cajai como cualquier otro tipo de valor, de modo quex.GetType() daría el mismo resultado quetypeof(int?) (en lugar de tirar unNullReferenceException)

Así que busqué un poco y, efectivamente, este comportamiento es específico para elNullable<T> tipo, especialmente definido en las especificaciones C # y VB.NET, y no reproducible en ningún tipo definido por el usuariostruct (C #) oStructure (VB.NET).

He aquí por qué sigo confundido.

Este comportamiento particular de boxeo y desempaquetado parece ser imposible de implementar a mano. Solo funciona porque C # y VB.NET le dan un tratamiento especial aNullable<T> tipo.

¿No es teóricamente posible que exista un lenguaje diferente basado en CLI dondeNullable<T> ¿No recibieron este tratamiento especial? Y no sería elNullable<T> tipo por lo tanto exhibircomportamiento diferente en diferentes idiomas?

¿Cómo C # y VB.NETlograr ¿este comportamiento? ¿Es compatible con el CLR? (Es decir, ¿permite el CLR que un tipo de alguna manera "anule" la forma en que está encuadrado, aunque C # y VB.NET lo prohíben?)

Es inclusoposible (en C # o VB.NET) para boxear unNullable<T> comoobject?

Respuestas a la pregunta(3)

Su respuesta a la pregunta