Запутался в боксе. Приведение -1 к Int64 создает исключение InvalidCastException - PullRequest
9 голосов
/ 13 октября 2010

Хорошо, я должен пропустить что-то чрезвычайно простое, но я потерян.

Учитывая это

object val = -1;
var foo = (Int32)(val);
var bar = (Int64)(val);

Приведение к броскам Int64 и исключение InvalidCastException.

Я понимаю, что это связано с какой-то странностью с боксом, но я не понимаю причины.

Из того, что я понимаю, val упакован как Int32 в первой строке.

Затем, когда я пытаюсь привести что-то, кроме Int32, выдается исключение InvalidCastException.Я предполагаю, что это означает, что я пытаюсь распаковать val как Int64, когда это на самом деле Int32?

Все еще кажется странным.Не может ли приведение распаковать значение и затем попытаться выполнить приведение?

Что-то вроде (Очевидно, это ужасно упрощено, возможно, коробочный тип неизвестен, так что это невозможно?):

object val = -1;
Int32 unboxed = (Int32)(val);
var bar = (Int64)(unboxed);

Кто-то (читай: Эрик Липперт) Приучите меня к обоснованию этого.

ОБНОВЛЕНИЕ: Из блога Эрика, в котором Рид разместил ссылку на этот краткий ответ, который я искал

"... Это было бы огромнымколичество кода для генерации, и это будет очень медленно. Код, конечно, настолько велик, что вы захотите поместить его в свой собственный метод и просто сгенерировать вызов. Вместо того, чтобы делать это по умолчанию, и всегда генерировать кодон медленный, большой и хрупкий, вместо этого мы решили, что распаковка может распаковывать только точный тип. Если вы хотите вызвать медленный метод, который делает все это, он доступен - вы всегда можете вызватьConvert.ToInt32, который выполняет весь этот анализ во время выполнения для вас. Мы даем вам выбор между «быстрым и точным» или «медленным и слабым», и разумное значение по умолчанию - первое. Если вы хотите второе, тогда вызовите метод.... "

1 Ответ

15 голосов
/ 13 октября 2010

Это потому, что вы не можете распаковать и выполнить конвертацию за одну операцию.Вы должны распаковать значение Int32 в Int32, а затем впоследствии преобразовать его тип.

Из-за этого требуется распаковать объект, а затем преобразовать в Int64:

object val = -1;
int foo = (Int32)val;
Int64 bar = (Int64)(Int32)val;

ЭрикЛипперт подробно рассказал об этом в своем блоге под названием Представительство и личность .

...