Как CLR знает тип объекта в штучной упаковке?

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

long l = 1;
object obj = (object)l;
double d = (double)obj;

Ответы

Ответ 1

Нет, он не помещается в нетипизированный объект. Для каждого типа значений в CLR имеется ссылочный тип в штучной упаковке. Таким образом, у вас будет что-то вроде:

public class BoxedInt32 // Not the actual name
{
    private readonly int value;
    public BoxedInt32(int value)
    {
        this.value = value;
    }
}

Этот тип в коробке напрямую не доступен на С#, хотя он находится в С++/CLI. Очевидно, что он знает оригинальный тип. Поэтому в С# у вас должен быть тип времени компиляции object для переменной, но это не означает, что фактический тип объекта.

См. спецификацию ECMA CLI или CLR через С# для более подробной информации.

Ответ 3

Джон Скит отвечает, почему; как о том, как обойти это, вот что вам нужно сделать:

long l = 1;
object obj = (object)l;
double d = (double)(long)obj;

Причина двойного актера - это; когда .NET распаковывает эту переменную, она знает, как ее можно распаковать в тип, из которого он был помещен в коробку (long в вашем примере.) После того, как вы распаковали его и у вас есть правильный примитив long, вы можете до double или любого другого типа, спрятанного от long.