Как 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 через С# для более подробной информации.
Ответ 2
Я отвечу на ваш вопрос здесь:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
Ответ 3
Джон Скит отвечает, почему; как о том, как обойти это, вот что вам нужно сделать:
long l = 1;
object obj = (object)l;
double d = (double)(long)obj;
Причина двойного актера - это; когда .NET распаковывает эту переменную, она знает, как ее можно распаковать в тип, из которого он был помещен в коробку (long
в вашем примере.) После того, как вы распаковали его и у вас есть правильный примитив long
, вы можете до double
или любого другого типа, спрятанного от long
.