C # вопрос о боксе - PullRequest
       60

C # вопрос о боксе

2 голосов
/ 07 октября 2008

Сначала два примера:

// This works
int foo = 43;
long lFoo = foo;

// This doesn't
object foo = (int)43;
long? nullFoo = foo as long?; // returns null
long lFoo = (long)foo; // throws InvalidCastException
if (foo.GetType() == typeof(int))
    Console.WriteLine("But foo is an int..."); // This gets written out

Теперь, я думаю, почему второй не работает из-за бокса. Целью этого кода является реализация IComparable. Мне нужен какой-то способ привести объект в long или ulong, в зависимости от ситуации, или, если это не так, чем выдавать ошибку. Я не хочу реализовывать проверки для каждого базового числового типа (byte, int, long, ubyte, ...). Я бы предпочел просто перехватить их в самом большом числовом типе и разобраться с ним таким образом. Мысли от всех умных людей здесь? Как я могу распаковать объект, предпочтительно избегая отражения, но я полагаю, если это единственный способ ... Или я просто не должен реализовывать не-дженериковую версию IComparable?

Edit:

Это похоже на работу, но похоже на ужасный взлом вокруг проблемы. Это только у меня так?

long lFoo = long.Parse(foo.ToString());

Ответы [ 3 ]

7 голосов
/ 07 октября 2008
object foo  = (int) 43;
long   lFoo = ((IConvertible) foo).ToInt64(null);
4 голосов
/ 07 октября 2008

Когда вы приводите к типу значения, вы действительно форсируете операцию unbox IL, которая требует, чтобы тип, которому вы приводите, соответствовал точно упакованному значению; нет конверсий, неявных или явных, которые могут происходить одновременно.

Обычно это означает, что вам нужно либо выполнить переключение, используя typecode (или if / else, если используются типы), либо, в вашем случае, пойти с проверкой на null, а затем Convert.ToInt64 (), которая правильно с этим справиться.

0 голосов
/ 07 октября 2008

Это не только вы, однако tryparse не вызывает исключения.

object foo = (int)43;
long outVal;
if(long.TryParse(foo.ToString(),out outVal))
{
//take action with correct value of long
}
else
{
//maybe passed you another type of object
}
...