In vielen MSIL-Listen habe ich Folgendes beobachtet:
System.Nullable`1<!0> etc ...
oder
class !0 etc ...
Was bedeutet das unter !0
diesen Umständen?
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 !n
als 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 !0
als "T" lesen . Oder verwenden Sie einen besseren Dekompiler.
Das ist ein generischer Typparameter.
Sie sind positionell.
Dekompilieren Sie generischen Code, um zu sehen, wie sie verwendet werden (vergleichen Sie IL mit C #).
!T
und!!T
, je nachdem, ob der generische Parameter der enthaltenden Klasse oder der Methode entspricht ... Dasselbe, wenn ich ildasmldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionary
odercall instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool)
. Die unformatierte IL verwendet jedoch ohnehin nur das Positionsargument - dies!TKey
ist 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
.