gpt4 book ai didi

c# - 为什么 C# 编译器为 GetType() 方法调用发出 callvirt 指令?

转载 作者:IT王子 更新时间:2023-10-29 04:14:09 26 4
gpt4 key购买 nike

我很想知道为什么会这样。请阅读下面的代码示例以及在每个部分下面的注释中发出的相应 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,这是否会产生类型安全问题?

最佳答案

参见 this Eric Gunnerson 的旧博文。

这是帖子的正文:

为什么 C# 总是使用 callvirt?

这个问题是在内部 C# 别名上提出的,我认为答案会引起普遍兴趣。这是假设答案是正确的——已经有一段时间了。

.NET IL 语言同时提供 call 和 callvirt 指令,callvirt 用于调用虚函数。但是,如果您查看 C# 生成的代码,您会发现即使在不涉及虚函数的情况下,它也会生成一个“callvirt”。为什么要这样做?

我回顾了我的语言设计说明,它们非常清楚地说明我们决定在 12/13/1999 使用 callvirt。不幸的是,他们没有捕获我们这样做的理由,所以我将不得不从我的内存中走出来。

我们从某人(可能是使用 C# 的 .NET 小组之一(认为当时尚未命名为 C#))那里得到一份报告,他们编写了在空指针上调用方法的代码,但他们没有不会出现异常,因为该方法没有访问任何字段(即“this”为空,但方法中没有任何内容使用它)。该方法随后调用了另一个确实使用了 this 点并抛出异常的方法,随后出现了一些令人头疼的问题。在他们弄明白之后,他们给我们发了一张便条。

我们认为能够在空实例上调用方法有点奇怪。 Peter Golde 进行了一些测试,以了解始终使用 callvirt 对性能的影响,它足够小,我们决定进行更改。

关于c# - 为什么 C# 编译器为 GetType() 方法调用发出 callvirt 指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/845657/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com