IL泛型 - 什么规则存在!T使用vs!0?

tos*_*hok 8 .net generics cil

我正在编写一个IL静态分析工具,我很难理解控制泛型类型参数的规则:

拿这个IL(来自IList<T>界面):

.property instance !T Item(
    int32 index
)
{
    .get instance !0 System.Collections.Generic.IList`1::get_Item(int32)
    .set instance void System.Collections.Generic.IList`1::set_Item(int32, !0)
}
Run Code Online (Sandbox Code Playgroud)

为什么!0那里而不是!T?我认为就VM而言,它们是等效的,当你保证拥有这些名字时,使用位置引用似乎很奇怪.

更新:来自KeyedCollection.ctor的另一个案例:

IL_0037:  newobj instance void class System.Collections.Generic.Dictionary`2<!TKey,!TItem>::'.ctor'(class System.Collections.Generic.IEqualityComparer`1<!0>)
IL_003c:  stfld class System.Collections.Generic.Dictionary`2<!0,!1> class System.Collections.ObjectModel.KeyedCollection`2<!0,!1>::dictionary
Run Code Online (Sandbox Code Playgroud)

cas*_*One 4

公共语言基础设施标准II 部分 - 元数据和文件格式中,第 7.1 条“类型”指出:

Type ::=        Description
--------        -----------
'!'             Generic parameter in a type definition, accessed by index from 0
Run Code Online (Sandbox Code Playgroud)

答案很简短:因为它在规范中。

长答案:这是我的猜测,但基本上,大多数 IL 命令都是基于堆栈的,并且始终使用位置引用作为参数。也就是说,将位置引用用于泛型是有意义的,以便维护 IL 中的通用模式/使用机制。