Offset

2015-06-13 21 views
5

Ich habe die folgende Klasse:Offset

[StructLayout(LayoutKind.Sequential)] 
class Class 
{ 
    public int Field1; 
    public byte Field2; 
    public short? Field3; 
    public bool Field4; 
} 

Wie kann ich das Byte erhalte Offset von Field4 ab Beginn des Klassendaten (oder Objekt-Header)? Um
zu illustrieren:

Class cls = new Class(); 
fixed(int* ptr1 = &cls.Field1) //first field 
fixed(bool* ptr2 = &cls.Field4) //requested field 
{ 
    Console.WriteLine((byte*)ptr2-(byte*)ptr1); 
} 

Die resultierende Offset ist, in diesem Fall 5, weil die Laufzeit tatsächlich Field3 bis zum Ende des Typs bewegt (und Pads es), wahrscheinlich, weil es seine Art generisch ist. Ich weiß, dass es Marshal.OffsetOf gibt, aber es gibt nicht verwalteten Offset zurück, nicht verwaltet.

Wie kann ich diesen Offset von einer FieldInfo Instanz abrufen? Gibt es dafür irgendeine .NET-Methode oder muss ich meine eigene schreiben und dabei alle Ausnahmen berücksichtigen (Schriftgröße, Abstand, explizite Versätze usw.)?

+0

@usr Gemeint 'Feld3'. Eigentlich ist es zu meiner Überraschung neu geordnet. Es wurde dieses Feld an das Ende der Klasse verschoben und aufgefüllt (debuggen und releasen, 32-Bit). Es kann etwas mit der Unfähigkeit zu tun haben, Zeiger generischer Typen zu erhalten. – IllidanS4

+1

Sie können nicht herausfinden, dass das verwaltete Objektlayout ein Implementierungsdetail ist. Anders als durch die Hintertür, die du bereits entdeckt hast. Die CLR nutzt dies, um das Layout zu optimieren und das Objekt so klein wie möglich zu machen, während es dennoch Ausrichtungsgarantien bietet. [StructLayout] wird nur bei Marshalling-Strukturen berücksichtigt. In diesem Fall gibt Marshal.SizeOf() den Offset an. –

+1

@Hans Aber Marshal.SizeOf gibt die nicht verwaltete Schriftgröße zurück, nicht die verwaltete. Ich dachte, LayoutKind.Explicit ist auf Strukturen geehrt, überlappende Felder sind der Beweis dafür, ohne Marshalling. – IllidanS4

Antwort

2

Mit einigen Tricks um TypedReference.MakeTypedReference, ist es möglich, den Bezug auf das Feld und den Anfang der Daten des Objekts zu erhalten, dann subtrahieren Sie einfach. Die Methode kann in SharpUtils gefunden werden.