2015-06-13 16 views
5

Ho la seguente classe:Ottenere campo non esplicito all'offset

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

come posso ottenere il byte di offset di Field4 a partire dall'inizio dei dati di classe (intestazione o oggetto)?
Per chiarire:

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

L'offset risultante è, in questo caso, 5, poiché il runtime effettivamente sposta Field3 alla fine del tipo (e pastiglie it), probabilmente perché il suo tipo è generico. So che c'è Marshal.OffsetOf, ma restituisce offset non gestito, non gestito.

Come posso recuperare questo offset da un'istanza FieldInfo? Esiste un metodo .NET utilizzato per questo, o devo scrivere il mio, tenendo conto di tutte le eccezioni (dimensione del tipo, padding, offset espliciti, ecc.)?

+0

@usr Significato 'Campo3'. In realtà, è riordinato, con mia sorpresa. Ha spostato quel campo fino alla fine della classe, inserendolo a sua volta (debug e release, 32-bit). Potrebbe avere qualcosa a che fare con l'incapacità di ottenere puntatori di tipi generici. – IllidanS4

+1

Non è possibile scoprirlo, il layout dell'oggetto gestito è un dettaglio di implementazione. Altro che attraverso la backdoor che hai già scoperto. Il CLR usa questo per ottimizzare il layout, rendendo l'oggetto il più piccolo possibile pur mantenendo le garanzie di allineamento. [StructLayout] è solo onorato nelle strutture di marshalling. In tal caso Marshal.SizeOf() fornisce l'offset. –

+1

@Hans Ma Marshal.SizeOf restituisce la dimensione del tipo non gestito, non quella gestita. Pensavo che LayoutKind.Explicit fosse onorato sulle strutture, i campi sovrapposti ne erano la prova, senza il marshalling. – IllidanS4

risposta

2

Con alcuni accorgimenti attorno allo TypedReference.MakeTypedReference, è possibile ottenere il riferimento al campo e all'inizio dei dati dell'oggetto, quindi solo sottrarre. Il metodo può essere trovato in SharpUtils.

Problemi correlati