Warum ist! 0 ein Typ in Microsoft Intermediate Language (MSIL)?

88

In vielen MSIL-Listen habe ich Folgendes beobachtet:

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

oder

class !0 etc ...

Was bedeutet das unter !0diesen Umständen?

Dragno
quelle

Antworten:

118

Dies ist eine Eigenart des Dekompilers, mit dem Sie eine .NET-Assembly betrachten. Es ist das Verhalten von ildasm.exe, andere wie Reflector oder ILSpy machen das richtig. Der Microsoft-Programmierer, der es geschrieben hat, hat eine Verknüpfung verwendet. Er generiert eine Zeichenfolge aus der IL, die nur das Typargument so anzeigt, wie es codiert ist, ohne den zusätzlichen Code zum Nachschlagen des Typargumentnamens in den Metadaten zu schreiben .

Sie müssen !nals n-tes Typargument des generischen Typs lesen . Wobei! 0 "Argument vom ersten Typ" bedeutet ,! 1 "Argument vom zweiten Typ" usw. bedeutet. Für Nullable <> wissen Sie, dass '! 0' 'T' aus dem MSDN-Artikel bedeutet.

Sie können auch auf so etwas stoßen !!T. Zwei Ausrufezeichen geben ein Typargument für eine generische Methode an . Diesmal ildasm.exe nicht die Art Argument Namen nachschlagen anstelle der Verwendung !!0. Warum der Programmierer die Verknüpfung zu generischen Typen, aber nicht zu generischen Methoden verwendet hat, ist schwer rückzuentwickeln. Ildasm ist ein ziemlich eigenartiges Programm und in einem C ++ - Codierungsstil geschrieben, der sich stark von anderem C ++ - Code in .NET unterscheidet. Nicht so diszipliniert, ungleich Null, dass dies die Aufgabe eines Praktikanten war :)

Das Suffix `1 auf" Nullable "ist eine normale Codierung für generische Typnamen. Es gibt an, dass der generische Typ ein Typargument hat. Mit anderen Worten, für Nullable <> werden Sie nie sehen, dass! 1 verwendet wird.

Also einfach !0als "T" lesen . Oder verwenden Sie einen besseren Dekompiler.

Hans Passant
quelle
35

Das ist ein generischer Typparameter.

Sie sind positionell.

Dekompilieren Sie generischen Code, um zu sehen, wie sie verwendet werden (vergleichen Sie IL mit C #).

Leppie
quelle
5
Wenn ich TryRoslyn benutze, verstehe ich es nicht ... goo.gl/ZZKE38 Ich bekomme !Tund !!T, je nachdem, ob der generische Parameter der enthaltenden Klasse oder der Methode entspricht ... Dasselbe, wenn ich ildasm
xanatos
@xanatos Nicht immer. Ich sehe auch Code wie ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryoder call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). Die unformatierte IL verwendet jedoch ohnehin nur das Positionsargument - dies !TKeyist bereits ein Versuch, die IL besser lesbar zu machen. Vielleicht funktioniert es nicht immer gut? Die ECMA-Spezifikation verwendet immer auch die Position !0/ !00.
Luaan