在许多MSIL清单中,我观察到以下内容:
System.Nullable`1<!0> etc ...
要么
class !0 etc ...
!0
在这种情况下是什么意思?
Answers:
这是您用来查看.NET程序集的反编译器的怪癖。这是ildasm.exe的行为,其他诸如Reflector或ILSpy的行为都可以解决此问题。编写此代码的Microsoft程序员采用了快捷方式,他从IL生成一个字符串,该字符串仅以编码方式显示类型实参,而无需编写额外的代码来在元数据中查找类型实参名称。
您需要将其读取!n
为通用类型的第n个类型参数。其中!0表示“第一类参数”,!1表示“第二类参数”,依此类推。对于Nullable <>,您从MSDN文章中知道'!0'表示'T'。
您可能还会遇到类似的东西!!T
。两个感叹号指示泛型方法的类型实参。这次,ildasm.exe 会查找类型实参名称,而不是使用!!0
。为什么程序员对通用类型而不是通用方法采用捷径是很难逆向工程的。Ildasm是一个非常古怪的程序,以C ++编码风格编写,与.NET中的其他C ++代码有很大不同。没有那么严格的纪律性,这是实习生分配的非零几率:)
“ Nullable”上的后缀1是通用类型名称的常规编码,它指示通用类型具有一个类型实参。换句话说,对于Nullable <>,您将永远不会看到使用!1。
因此简单地读!0
作“ T”。或使用更好的反编译器。
那是一个通用的类型参数。
他们是有立场的。
反编译一些通用代码以查看其用法(比较IL与C#)。
ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionary
或的代码call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool)
。原始IL无论如何都只使用位置参数-这!TKey
已经是尝试使IL更具可读性。也许它并不总是能正常工作?ECMA规范也始终使用位置!0
/ !00
。
!T
和!!T
,这取决于泛型参数是包含类还是方法的……如果我使用ildasm,则相同