Мой вопрос + ответ связан, и я делаю выражение и мета-выражение, которое может соответствовать произвольным (конечным) уровням вложенности. Это довольно изящно, но что еще вы можете ожидать? Используйте обратные ссылки в матче, если ваш движок поддерживает его.
Значение в коробке может быть отменено только для переменной того же типа. Это, казалось бы, странное ограничение - очень важная оптимизация скорости, которая сделала .NET 1.x возможной до того, как появились дженерики. Вы можете узнать больше об этом в этом ответе .
Вам не нужно перескакивать через несколько обруча, простые типы значений реализуют интерфейс IConvertible. Вы вызываете с помощью класса Convert:
object o = 12m;
int ix = Convert.ToInt32(o);
Когда вы это делаете, вы неявно вставляете десятичный d
в базовый объект:
object o = d;
Вы не можете напрямую вставлять значения в коробке без их первого распаковки, поэтому приведение непосредственно к int, как и в следующем, не выполняется:
int x = (int)o;
Однако, выполняя это (промежуточное отбрасывание до десятичной дроби):
int x = (int)(decimal)o;
Вы сначала распаковываете o
, что означает, что вы извлекаете десятичное значение, , затем , переводящее значение unboxed decimal в int, которое работает, потому что C # поддерживает деление на десятичные числа на int.
decimal
имеет явный оператор сбрасывания до int
. object
не:
decimal d = 10m;
object o = d;
int x = (int)d; // OK, calls decimal.explicit operator int(d).
int y = (int)o; // Invalid cast.
Что вам нужно подумать, так это то, что бокс и распаковка - это не просто конверсия. Вы просто «обертываете» тип объекта «вокруг» начального десятичного типа. Вот почему вам нужно сначала распаковать объект, прежде чем вы сможете преобразовать его в целое число.