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.)?
@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
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. –
@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