Почему (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.

Ответ 4

Что вам нужно подумать, так это то, что бокс и unboxing - это не просто конверсия. Вы просто "обертываете" тип объекта "вокруг" начального десятичного типа. Вот почему вам нужно сначала распаковать объект, прежде чем вы сможете преобразовать его в целое число.