Die Instanzen des Typs sind nicht speicherbar

8
  • Gibt es eine Möglichkeit, einen Typ (oder besser, eine Schnittstelle) zu markieren, damit keine Instanzen in einem Feld gespeichert werden können (ähnlich wie TypedReference und ArgIterator )?
  • Genauso gibt es eine Möglichkeit, zu verhindern, dass Instanzen anonyme Methoden durchlaufen und - im Allgemeinen - das Verhalten der beiden oben genannten Typen zu imitieren?
  • Kann dies durch ILDasm oder allgemeiner durch IL-Bearbeitung geschehen? Da UnconstrainedMelody durch die binäre Bearbeitung einer kompilierten Assembly normalerweise nicht erreichbare Ergebnisse erzielt, ist es vielleicht möglich, bestimmte Zeichen zu "markieren" Typen (oder besser, abstrakte oder Marker-Schnittstellen) durch den gleichen Ansatz.

Ich bezweifle, dass es im Compiler fest codiert ist, weil die Dokumentation für den Fehler CS0610 sagt:

  

Es gibt einige Typen, die nicht als Felder oder Eigenschaften verwendet werden können. Diese Typen umfassen ...

Was meiner Meinung nach darauf hindeutet, dass die Typenreihe so erweitert werden kann - Aber ich könnte mich irren.

Ich habe ein wenig auf SO gesucht und während ich das verstehe einen Compiler-Fehler programmgesteuert zu erzeugen, kann nicht durchgeführt werden, ich konnte keine Quelle finden, die besagt, dass bestimmte" spezielle "Typen nicht repliziert werden konnten.

Auch wenn die Frage meist akademischer Natur ist, könnte es eine Antwort geben. Zum Beispiel könnte es manchmal nützlich sein, sicher zu sein, dass die Lebensdauer eines bestimmten Objekts auf den Methodenblock beschränkt ist, der es erstellt.

BEARBEITEN: RuntimeArgumentHandle ist ein weiterer (nicht erwähnter) nicht speicherbarer Typ.

EDIT 2: Wenn es irgendeinen Nutzen bringen kann, scheint es, dass die CLR diese Typen auch anders behandelt, wenn nicht nur der Compiler (immer vorausgesetzt, dass die Typen in der Nr anders als andere). Das folgende Programm wird zum Beispiel eine TypeLoadException in Bezug auf TypedReference* werfen. Ich habe es angepasst, um es kürzer zu machen, aber Sie können es umgehen, was Sie wollen. Wenn Sie den Typ des Zeigers beispielsweise in void* ändern, wird die Ausnahme nicht ausgelöst.

%Vor%     
Mir 16.01.2013, 16:02
quelle

2 Antworten

5

Okay. Das ist keine vollständige Analyse, aber ich vermute, dass es ausreicht, um zu bestimmen, ob Sie das tun können, und zwar auch, indem Sie IL - was ich, soweit ich es beurteilen kann, nicht tun können.

Ich habe auch beim Betrachten der dekompilierten Version mit dotPeek nichts besonderes über diesen bestimmten Typ / diese speziellen Typen dort, Attribut-weise oder anders gesehen:

%Vor%

Also, das ist geschehen, ich habe versucht, eine solche Klasse mit System.Reflection.Emit zu erstellen:

%Vor%

Wenn Sie es ausführen, wird eine TypeLoadException ausgelöst, deren Stack-Trace Sie auf System.Reflection.Emit.TypeBuilder.TermCreateClass verweist. Also ging ich danach mit dem Decompiler, was mir folgendes gab:

%Vor%

Zeigen Sie auf die nicht verwalteten Teile der CLR. An diesem Punkt, um nicht besiegt zu werden, grub ich in die gemeinsamen Quellen für die Referenzversion der CLR. Ich werde nicht die ganze Durchzeichnung durchmachen, die ich gemacht habe, um zu vermeiden, dass diese Antwort über alle sinnvolle Verwendung aufgebläht wird, aber schließlich landen Sie in der Funktion "MethodTableBuilder :: SetupMethodTable2" in "\ clr \ src \ vm \ class.cpp" ( das scheint auch Feldbeschreibungen einzurichten), wo Sie diese Zeilen finden:

%Vor%

und

%Vor%

Letzteres bezieht sich auf Informationen in \ src \ inc \ cortypeinfo.h, also:

%Vor%

(Es ist tatsächlich der einzige Typ von ELEMENT_TYPE_TYPEDBYREF in dieser Liste.)

ContainsStackPtr () wird dann an verschiedenen Stellen anderswo verwendet, um zu verhindern, dass diese bestimmten Typen verwendet werden, einschließlich in Feldern - von \ src \ vm \ class.cp, MethodTableBuilder :: InitializeFieldDescs ():

%Vor%

Wie auch immer: Um eine lange, lange, lange Geschichte kurz zu machen, scheint es so zu sein, dass die Typen, die auf diese Weise nicht speicherbar sind, effektiv in die CLR codiert sind und somit wenn Sie sich ändern wollen Die Liste oder ein IL bieten, um Typen als nicht speicherbar zu markieren, Sie werden ziemlich viel Mono oder die Shared-Source-CLR nehmen und Ihre eigene Version ausgliedern müssen.

    
Cerebrate 19.01.2013, 16:16
quelle
2

Ich konnte in der IL nichts finden, was darauf hindeutete, dass diese Typen in irgendeiner Weise besonders sind. Ich weiß, dass der Compiler viele, viele spezielle Fälle hat, wie zum Beispiel die Umwandlung von int / Int32 in den internen Typ int32 , oder viele Dinge, die zu Nullable struct gehören. Ich vermute sehr, dass diese Typen auch Sonderfälle sind.

Eine mögliche Lösung wäre Roslyn , von der ich erwarte, dass Sie eine solche Einschränkung erstellen können .

    
Kendall Frey 16.01.2013 16:26
quelle

Tags und Links