2012-10-04 120 views
8

我刚从一个让我疯狂的同事得到了这个测验。对于这个代码片段:可空类型GetType()抛出异常

var x = new Int32?(); 
string text = x.ToString(); // No exception 
Console.WriteLine(text); 
Type type = x.GetType(); // Bang! 

为什么在第一部分的ToString()的工作没有出现任何的异常,然后调用的GetType()抛出一个NullReferenceException?

回答

17

ToStringoverridden in Nullable<T>,所以没有拳击参与打电话。

GetType()不是一个虚拟的方法,所以不是(也不能)重写,所以在调用之前将值装箱...并且装填可空值类型的空值给出空引用。

其原因拳击是在C#4规范的7.5.5节:

M如果处于引用类型声明的实例函数成员:

  • ..
  • 如果E的类型是值型,则执行装箱转换(4.3.1)以将E转换为型和E在以下步骤中被认为是object类型。在这种情况下,M只能是System.Object

注意的成员,如果你有:

var x = new Int32?(10); 

你再次结束与类型是一样的typeof(int),由于拳击。无法创建值foo,因此foo.GetType()使用正常的GetType()方法返回可为空的值类型。 (您可以创建过程中的一个GetType()方法,但是这是一个枝节问题:)

(使用“砰!”暗示说测验可能是我的。道歉笔者驱动你疯了,如果是这样的case)。

+0

好吧..但是,为什么然后用最后一行替换:var boxed =(Int32)x;抛出InvalidOperationException而不是?是不是拳击,应该抛出同样的例外? – kabaros

+0

@kabaros:不,根本不是拳击 - “Int32?”和“Int32”都不是引用类型。这是C#4规范第6.2.3节中描述的明确转换。 –

+1

哦,当然,这是非常有道理的。非常感谢。顺便说一句好书,所以你原谅我们疯狂:) – kabaros

相关问题