【发布时间】:2009-05-10 16:56:33
【问题描述】:
我很想知道为什么会这样。请阅读下面的代码示例以及每个部分下方的 cmets 中发出的相应 IL:
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
为什么编译器为第一部分生成 callvirt 而为第二部分生成 call?编译器是否有任何理由会为非虚拟方法发出 callvirt 指令?如果在某些情况下编译器会为非虚拟方法发出callvirt,这是否会给类型安全带来问题?
【问题讨论】:
-
非常好的问题......让我伸出手去拿我的书。
-
总结:案例(1)调用虚方法:生成callvirt。案例(2)在可空接收器上调用实例方法:生成 callvirt 以获取廉价的空检查——是的,这是类型安全的。案例(3)在已知的不可空接收器上调用实例方法:生成对避免空检查的调用。您的第一个示例属于 (2) 类,您的第二个示例属于 (3) 类。 (编译器知道 new 永远不会返回 null,因此不需要再次检查。)
-
感谢 Eric,空值检查很有意义。您的评论加上 Gishu 的回答让事情变得更加清晰! :)
标签: c# compiler-construction il type-safety