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 指令?
基础教程推荐
- 如何激活MC67中的红灯 2022-01-01
- MS Visual Studio .NET 的替代品 2022-01-01
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- SSE 浮点算术是否可重现? 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- c# Math.Sqrt 实现 2022-01-01