Чому! 0 - це тип на проміжній мові Microsoft (MSIL)?


88

У багатьох списках MSIL я спостерігав наступне:

System.Nullable`1<!0> etc ...

або

class !0 etc ...

Що означає !0в цих обставинах?

Відповіді:


118

Це химерність декомпілятора, який ви використовуєте для перегляду збірки .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як "Т". Або скористайтеся кращим декомпілятором.


35

Це загальний параметр типу.

Вони позиційні.

Декомпілюйте загальний код, щоб побачити, як вони використовуються (порівняйте IL проти C #).


5
Якщо я використовую TryRoslyn, я його не отримую ... goo.gl/ZZKE38 я отримую !Tі !!T, залежно від того, чи є загальний параметр класом, що містить, або методом ... Те саме, якщо я використовую ildasm
xanatos

@xanatos Не завжди. Я також бачу код типу ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryor call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). Сирий ІЛ у будь-якому випадку використовує лише позиційний аргумент, проте - !TKeyце вже спроба зробити ІЛ більш читабельним. Може це не завжди працює добре? Специфікація ECMA завжди використовує також позиційний !0/ !00.
Luaan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.