Почему (int) (объект) 10m бросает исключение "Указанный приведение недействителен"?
Почему этот явный бросок бросает исключение Specified cast is not valid.?
decimal d = 10m;
object o = d;
int x = (int)o;
Но это работает:
int x = (int)(decimal)o;
Ответ 1
Коробчатое значение может быть заменено только на переменную того же типа. Это, казалось бы, странное ограничение - очень важная оптимизация скорости, которая сделала .NET 1.x возможной до того, как появились дженерики. Вы можете прочитать об этом в этом ответе.
Вам не нужно перепрыгивать через несколько обручей, простые типы значений реализуют интерфейс IConvertible. Который вы вызываете с помощью класса Convert:
object o = 12m;
int ix = Convert.ToInt32(o);
Ответ 2
Когда вы это сделаете, вы неявно вставляете десятичный d в базовый объект:
object o = d;
Вы не можете напрямую вставлять значения в коробке без их первого распаковки, поэтому приведение непосредственно к int, как показано ниже, не выполняется:
int x = (int)o;
Однако, делая это (промежуточное литье с десятичной точностью):
int x = (int)(decimal)o;
Вы сначала распаковываете o, что означает, что вы извлекаете десятичное значение, а затем деблокируете десятичное значение unboxed в int, что работает, потому что С# поддерживает литье десятичных знаков в ints.
decimal d = 10m;
object o = d;
int x = (int)d; // OK, calls decimal.explicit operator int(d).
int y = (int)o; // Invalid cast.
Ответ 4
Что вам нужно подумать, так это то, что бокс и unboxing - это не просто конверсия. Вы просто "обертываете" тип объекта "вокруг" начального десятичного типа. Вот почему вам нужно сначала распаковать объект, прежде чем вы сможете преобразовать его в целое число.