2008-10-07 61 views
2

一,两个例子:C#拳击问题

// 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。我需要某种方式将对象强制为长或长,或者如果不是,则抛出错误。我不想为每个基本的数字类型(byte,int,long,ubyte,...)实现检查。我宁愿用最大的数字类型来捕获它们并以这种方式处理它。来自这里所有聪明人的想法?我怎样才能解开对象,最好避免反射,但我想如果这是唯一的方法......或者我应该只是不实施非泛型版本IComparable

编辑:

这似乎是工作,但似乎是解决该问题一个可怕的黑客。只有我吗?

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

我很想看看究竟为什么你需要做到这一点。这与IComparable有什么关系? – 2008-10-07 11:52:34

回答

7
object foo = (int) 43; 
long lFoo = ((IConvertible) foo).ToInt64(null); 
+0

这实际上可行...... Hurray适用于继承接口的基本类型。从来没有完全理解这一部分,但有用的都不是。 – 2008-10-07 03:41:49

4

当您铸造你真的迫使拆箱IL操作的值类型,这需要的类型你铸造比赛准确装箱值;没有可以同时发生的隐式或显式转换。

这通常意味着你需要使用typecode(或if/else,如果使用类型)进行切换,或者在你的情况下,检查null,然后是Convert.ToInt64(),应该正确处理它。

+0

它实际上并不需要*精确*匹配。您可以取消装箱枚举作为其基础类型,反之亦然(尽管类型信息真的在那里)。您也可以取消选择适当的可空类型。 CLR允许有一些类似的奇数转换,例如int []到uint []。 – 2008-10-07 05:30:26

0

它不只是你,但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 
} 
+0

这是*不*要走的路。除了效率更低之外,我相信不能保证ToString()生成的字符串格式实际上可以通过Parse/TryParse()立即解析(即不是所有的方式都会往返) – tomasr 2008-10-07 02:58:52