Why is the C# compiler emitting a callvirt instruction for a GetType() method call?(为什么 C# 编译器会为 GetType() 方法调用发出 callvirt 指令?)
问题描述
我很想知道为什么会这样.请阅读下面的代码示例以及每个部分下方注释中发出的相应 IL:
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()
}
}
为什么编译器为第一部分发出 callvirt
而为第二部分发出 call
?编译器是否有任何理由会为非虚拟方法发出 callvirt
指令?如果在某些情况下,编译器会为非虚拟方法发出 callvirt
,这是否会给类型安全带来问题?
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?
推荐答案
只是谨慎行事.
技术上 C# 编译器并不总是使用 callvirt
Technically C# compiler doesn't always use callvirt
对于静态方法 &在值类型上定义的方法,它使用 call
.大多数是通过 callvirt
IL 指令提供的.
For static methods & methods defined on value types, it uses call
. The majority is provided via the callvirt
IL instruction.
两者之间的不同之处在于 call
假定用于进行调用的对象"不为空.另一方面,callvirt
检查 not null 并在需要时抛出 NullReferenceException.
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.
- 对于静态方法,对象是类型对象,不能为空.值类型同上.因此
call
用于它们 - 更好的性能. - 对于其他语言,语言设计者决定使用
callvirt
,以便 JIT 编译器验证用于进行调用的对象不为空.即使对于非虚拟实例方法.. 他们更看重安全而不是性能.
- 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.
另请参阅:Jeff Richter 在这方面做得更好 - 在他通过 C# 2nd Ed 在 CLR 中的设计类型"一章中
这篇关于为什么 C# 编译器会为 GetType() 方法调用发出 callvirt 指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么 C# 编译器会为 GetType() 方法调用发出 callvirt 指令?
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- 如何用自己压缩一个 IEnumerable 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- 输入按键事件处理程序 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01