Почему происходит сбой приведения от короткого к внутреннему? - PullRequest
12 голосов
/ 16 марта 2012

У нас есть некоторый код, который архивирует данные из базы данных Microsoft Access в базу данных MS SQL Server.Предполагая, что у нас есть считыватель данных, уже заполненный из таблицы Access, и мы добавляем параметр в SqlCommand при подготовке к вставке, у нас есть тип-трансляция, которая не выполняется.Вот код:

oSqlServerDbCmd_ForInsert.Parameters.AddWithValue("@Duration",
     (int) oReader["Duration"]);

Поле oReader на самом деле является целым числом доступа, что является сокращением в C #.Если мы приведем к сокращению здесь нет проблем.Однако, если мы приводим к int, код генерирует исключение InvalidCastException.Возможно, я неверно истолковываю это из документации MSDN :

"Существует предопределенное неявное преобразование из short в int, long, float, double или decimal."

... но звучит так, как будто это должно сработать (по моим соображениям, если неявное преобразование определено, почему бы явное приведение типа не сработало?).Я понимаю, что приведение не является даже необходимым, потому что AddWithValue принимает объект, поэтому мы фактически удалили приведение из нашего кода, но я хотел бы увидеть объяснение того, почему это приведение было неудачным только в случае, если мы столкнемся с чем-то подобным вбудущее.

Ответы [ 2 ]

18 голосов
/ 16 марта 2012

В ваших руках есть экземпляр распаковка .В частности, при распаковке вы можете распаковать только тот тип значения, который был изначально помещен в коробку;если этот тип A и вы распаковываете в B, не имеет значения, существует ли неявное преобразование из A в B (распаковка все равно не удастся).

См. * 1009 Эрика Липперта* Классическое сообщение в блоге на эту тему для объяснения.

5 голосов
/ 16 марта 2012

Вы должны привести к очень конкретному типу, так как вы распаковываете - проблема в том, что oReader["Duration"] возвращает object экземпляр:

short myShort = 42;
object o = myShort;
int myInt = (int)o; //fails

Это будет успешным, если вы сначала приведете к короткомутогда к int:

(int) (short) oReader["Duration"]
...