Во многих списках MSIL я заметил следующее:
System.Nullable`1<!0> etc ...
или
class !0 etc ...
Что означает !0
в этих обстоятельствах?
Это особенность декомпилятора, который вы используете для просмотра сборки .NET. Это поведение ildasm.exe, другие, такие как Reflector или ILSpy, понимают это правильно. Программист Microsoft, написавший это, взял ярлык, он генерирует строку из IL, которая просто отображает аргумент типа в том виде, в каком он закодирован, без написания дополнительного кода для поиска имени аргумента типа в метаданных.
Вам нужно читать !n
как аргумент n-го типа универсального типа. Где! 0 означает «аргумент первого типа»,! 1 означает «аргумент второго типа» и т.д. Для Nullable <> вы знаете, что '! 0` означает' T 'из статьи MSDN.
Вы также можете столкнуться с чем-то вроде !!T
. Два восклицательных знака обозначают аргумент типа для универсального метода . На этот раз, ildasm.exe ли искать имя аргумента типа вместо использования !!0
. Почему программист использовал ярлык для универсальных типов, а не для универсальных методов, трудно реконструировать. Ildasm - довольно необычная программа, написанная в стиле программирования C ++, который сильно отличается от другого кода C ++ в .NET. Не такие дисциплинированные, ненулевые шансы, что это задание стажера :)
Суффикс `1 в" Nullable "является нормальной кодировкой для имен универсальных типов, он указывает, что универсальный тип имеет один аргумент типа. Другими словами, для Nullable <> вы никогда не увидите, что используется! 1.
Так что просто читайте !0
как "Т". Или воспользуйтесь декомпилятором получше.
Это параметр универсального типа.
Они позиционные.
Декомпилируйте некоторый общий код, чтобы увидеть, как они используются (сравните IL с C #).
!T
и!!T
, в зависимости от того, является ли общий параметр содержащим класс или метод ... То же самое, если я использую ildasmldfld 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
.