Mengapa! 0 termasuk dalam Microsoft Intermediate Language (MSIL)?

89

Di banyak daftar MSIL, saya telah mengamati hal-hal berikut:

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

atau

class !0 etc ...

Apa artinya !0dalam keadaan seperti ini?

Dragno
sumber

Jawaban:

119

Ini adalah kekhasan dari decompiler yang Anda gunakan untuk melihat rakitan .NET. Ini adalah perilaku ildasm.exe, yang lain seperti Reflector atau ILSpy mendapatkan hak ini. Pemrogram Microsoft yang menulisnya mengambil jalan pintas, dia menghasilkan string dari IL yang hanya menampilkan argumen tipe seperti yang dikodekan, tanpa menulis kode tambahan untuk mencari nama argumen tipe dalam metadata.

Anda perlu membaca !nsebagai argumen tipe ke-n dari tipe generik. Dimana! 0 berarti "argumen tipe pertama",! 1 berarti "argumen tipe kedua", dan sebagainya. Untuk Nullable <>, Anda tahu bahwa '! 0` berarti' T 'dari artikel MSDN.

Anda mungkin juga menemukan sesuatu seperti !!T. Dua tanda seru menunjukkan argumen tipe untuk metode generik . Kali ini, ildasm.exe tidak mencari jenis nama argumen daripada menggunakan !!0. Mengapa programmer mengambil jalan pintas pada tipe generik tetapi tidak pada metode generik sulit untuk merekayasa balik. Ildasm adalah program yang cukup unik dan ditulis dalam gaya pengkodean C ++ yang sangat berbeda dari kode C ++ lainnya di .NET. Tidak disiplin, kemungkinan tidak nol bahwa ini adalah tugas magang :)

Sufiks `1 pada" Nullable "adalah pengkodean normal untuk nama tipe generik, ini menunjukkan tipe generik memiliki satu argumen tipe. Dengan kata lain, untuk Nullable <> Anda tidak akan pernah melihat! 1 digunakan.

Jadi cukup dibaca !0sebagai "T". Atau gunakan decompiler yang lebih baik.

Hans Passant
sumber
35

Itu adalah parameter tipe generik.

Mereka posisional.

Dekompilasi beberapa kode umum untuk melihat bagaimana mereka digunakan (bandingkan IL vs C #).

leppie
sumber
5
Jika saya menggunakan TryRoslyn, saya tidak mengerti ... goo.gl/ZZKE38 Saya mengerti !Tdan !!T, tergantung apakah parameter generik dari kelas yang memuat atau metode ... Sama jika saya menggunakan ildasm
xanatos
@xanTidak selalu. Saya juga melihat kode seperti ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryatau call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). IL mentah hanya menggunakan argumen posisi, meskipun - !TKeyini sudah merupakan upaya untuk membuat IL lebih mudah dibaca. Mungkin tidak selalu berhasil dengan baik? Spesifikasi ECMA selalu menggunakan posisi !0/ !00juga.
Luaan