我会尝试仔细回答,因为这是 ECMA 中最不太明确的主题之一,但也许我能够对此做出一些说明。
您可以跳到“回到您的问题”部分查看最终答案。
答案有点长,因为我想提供参考,所以我不会写我的观点,而是引用。我希望它足够容易理解。如果没有,我将编辑答案并提供更多解释。
引文中的强调是我的。一些引言被删掉了。
EXPLICITTHIS (0x40) 位只能设置在函数指针的签名中:签名其
MethodDefSig 前面是 FNPTR
来自 CoreCLR
EXPLICITTHIS 和本机调用转换仅适用于独立信号(对于愈伤组织)
函数指针是一种调用非托管方法的方法。
非托管方法也可以通过函数指针调用。
函数指针可以通过调用calli
操作说明
方法指针应存储其签名的方法的入口点地址
是method-signature-compatible-with
方法指针的类型。可以通过使用方法指针和calli
操作说明。
更多相关信息
正确的 CIL 要求函数指针包含其签名的方法的地址
是method-signature compatible-with
由指定的callsitedescr
并且这些论点
如果需要,正确对应于目标函数的 this 指针的类型,并且
参数。为了签名匹配的目的,HASTHIS 和 EXPLICITTHIS 标志是
被忽视;两个签名中的所有其他项目必须相同。
And
The calli
指令包括一个call site description
其中包括有关本机调用的信息
应该用于调用该方法的约定。正确的 CIL 代码应在calli
与正在调用的方法的调用约定相匹配的指令。
调用站点说明
呼唤站点
描述(表示为元数据标记stand-alone call signature
) 提供:
• 传递的参数数量。
• 这每个参数的数据类型。
• 它们在调用堆栈上的放置顺序。
• 要使用的本机调用约定
方法签名与均值兼容
方法签名类型 T 与方法签名类型 U 方法签名兼容,如果
并且仅当:
1. 对于每个签名,独立地,如果该签名是针对其携带的实例方法
这个的类型。 [注意:对于实例方法指针的签名始终如此
由 ldvirtftn 指令生成。
2、T和U的调用约定要完全匹配,忽略区别
静态方法和实例方法之间(即 this 参数,如果有的话,不被处理
特别)。
回到你的问题
- 编译器什么时候设置它们?
- 是否有使用这种调用约定组合的示例(在“现实世界”托管程序中)?
ExplicitThis
can仅在通过调用函数指针时使用calli
操作说明。
AFAIK C# 编译器not生成calli
指令,因此您不会看到任何设置该位的 C# 代码。
参考
C#编译器不会生成calli指令 https://blogs.msdn.microsoft.com/shawnfa/2004/06/14/calli-is-not-verifiable/
罗斯林源代码 https://github.com/dotnet/roslyn
EXPLICITTHIS 和本机调用转换仅适用于独立信号(对于愈伤组织) https://github.com/dotnet/coreclr/blob/03f0b6d5f97a5d65387cad5fd0f60342d3118047/src/utilcode/util.cpp#L2140
引擎盖下的签名 https://www.codeproject.com/Articles/42649/%2FArticles%2F42649%2FNET-file-format-Signatures-under-the-hood-Part-1
ECMA https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf