我刚刚从同事那里得到这个让我疯狂的测验。对于这段代码:
var x = new Int32?();
string text = x.ToString(); // No exception
Console.WriteLine(text);
Type type = x.GetType(); // Bang!
为什么第一部分.ToString()在不抛出异常的情况下工作,然后调用GetType()会抛出NullReferenceException?
答案 0 :(得分:19)
ToString
是overridden in Nullable<T>
,因此不需要装箱来进行通话。
GetType()
不是虚方法,因此不会(也不能)重写,因此在调用之前将值装箱...并且装入可空值的空值type给出一个空引用。
拳击的原因在C#4规范的第7.5.5节中:
如果
M
是在引用类型中声明的实例函数成员:
- ...
- 如果
的成员E
的类型是值类型,则执行装箱转换(4.3.1)以将E
转换为类型object
,并且E
在以下步骤中被视为object
类型。在这种情况下,M
只能是System.Object
请注意,如果您有:
var x = new Int32?(10);
你最终得到的类型与typeof(int)
相同,这也是因为拳击。无法使用常规foo
方法创建值foo.GetType()
,以便GetType()
返回可为空的值类型。 (当然,你可以创建一个新的 GetType()
方法,但这是一个副问题:)
(使用“Bang!”表示所述测验的作者可能是我。如果是这样的话,就会让你发疯的道歉。)