У багатьох списках MSIL я спостерігав наступне:
System.Nullable`1<!0> etc ...
або
class !0 etc ...
Що означає !0
в цих обставинах?
Відповіді:
Це химерність декомпілятора, який ви використовуєте для перегляду збірки .NET. Це поведінка ildasm.exe, інші, такі як Reflector або ILSpy, розуміють це правильно. Програміст Microsoft, який написав його, скористався ярликом, він генерує рядок з ІЛ, який просто відображає аргумент типу так, як він кодується, не записуючи зайвого коду для пошуку імені аргументу типу в метаданих.
Вам потрібно читати !n
як аргумент n-го типу загального типу. Де! 0 означає "аргумент першого типу",! 1 означає "аргумент другого типу" тощо. Для Nullable <> ви знаєте, що "! 0" означає "T" зі статті MSDN.
Ви також можете зустріти щось подібне !!T
. Два знаки оклику вказують на аргумент типу для загального методу . На цей раз, ildasm.exe чи шукати ім'я аргументу типу замість використання !!0
. Чому програміст використав ярлик для загальних типів, а не для загальних методів, важко змінити. Ildasm - досить химерна програма, написана у стилі кодування на C ++, який сильно відрізняється від іншого коду на C ++ у .NET. Не настільки дисципліновано, ненульові шанси, що це було завдання стажиста :)
Суфікс `1 у" Nullable "є звичайним кодуванням загальних імен типів, це означає, що загальний тип має один аргумент типу. Іншими словами, для Nullable <> ви ніколи не побачите! 1 використовується.
Тож просто читайте !0
як "Т". Або скористайтеся кращим декомпілятором.
Це загальний параметр типу.
Вони позиційні.
Декомпілюйте загальний код, щоб побачити, як вони використовуються (порівняйте IL проти C #).
ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionary
or call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool)
. Сирий ІЛ у будь-якому випадку використовує лише позиційний аргумент, проте - !TKey
це вже спроба зробити ІЛ більш читабельним. Може це не завжди працює добре? Специфікація ECMA завжди використовує також позиційний !0
/ !00
.
!T
і!!T
, залежно від того, чи є загальний параметр класом, що містить, або методом ... Те саме, якщо я використовую ildasm