为什么C#编译器为GetType()方法调用发出callvirt指令? [英] Why is the C# compiler emitting a callvirt instruction for a GetType() method call?

查看:260
本文介绍了为什么C#编译器为GetType()方法调用发出callvirt指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很想知道为什么会发生这种情况。请阅读下面的代码示例和在每个部分下面的注释中发出的相应的IL:

 使用System; 

类程序
{
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实例类[mscorlib] System.Type [mscorlib] System.Object :: GetType()

new Object()。GetType();

// L_000e:newobj instance void [mscorlib] System.Object ::。ctor()
// L_0013:调用实例类[mscorlib] System.Type [mscorlib] System.Object :: GetType()
}
}

callvirt 用于第一部分,但是调用用于第二部分?是否有任何理由编译器会为非虚方法发出 callvirt 指令?如果在某些情况下,编译器将为非虚方法发出 callvirt ,这会对类型安全造成问题?



技术上C#编译器不会 >总是使用 callvirt



在值类型上定义的方法,它使用 call 。大多数通过 callvirt IL指令提供。



两者之间的投票差异是事实 call 假设用于进行调用的对象不为空。 callvirt 另一方面检查不为null并且如果需要则抛出NullReferenceException。




  • 对于静态方法,对象是一个类型对象,不能为null。同值类型。因此, call 用于他们 - 更好的性能。

  • 对于其他人,语言设计师决定使用 callvirt ,因此JIT编译器会验证用于调用的对象不为空。



另请参见:Jeff Richter做得更好在这里 - 在他的设计类型章通过C#第二编辑CLR通过


I am curious to know why this is happening. Please read the code example below and the corresponding IL that was emitted in comments below each section:

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()
    }
}

Why did the compiler emit a callvirt for the first section but a call for the second section? Is there any reason that the compiler would ever emit a callvirt instruction for a non-virtual method? And if there are cases in which the compiler will emit a callvirt for a non-virtual method does this create problems for type-safety?

解决方案

Just playing safe.

Technically C# compiler doesn't always use callvirt

For static methods & methods defined on value types, it uses call. The majority is provided via the callvirt IL instruction.

The difference that swung the vote between the two is the fact that call assumes the "object being used to make the call" is not null. callvirt on the other hand checks for not null and throws a NullReferenceException if required.

  • For static methods, the object is a type object and cannot be null. Ditto for value types. Hence call is used for them - better performance.
  • For the others, the language designers decided to go with callvirt so the JIT compiler verifies that the object being used to make the call is not null. Even for non-virtual instance methods.. they valued safety over performance.

See Also: Jeff Richter does a better job at this - in his 'Designing Types' chapter in CLR via C# 2nd Ed

这篇关于为什么C#编译器为GetType()方法调用发出callvirt指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆