У меня есть следующий класс:Получить без явного поля смещения
[StructLayout(LayoutKind.Sequential)]
class Class
{
public int Field1;
public byte Field2;
public short? Field3;
public bool Field4;
}
Как я могу получить байт смещения Field4
, начиная с начала (или заголовка объекта) данных класса?
Для иллюстрации:
Class cls = new Class();
fixed(int* ptr1 = &cls.Field1) //first field
fixed(bool* ptr2 = &cls.Field4) //requested field
{
Console.WriteLine((byte*)ptr2-(byte*)ptr1);
}
Полученное смещение, в данном случае, 5, потому что на самом деле во время выполнения перемещает Field3
до конца типа (и его колодки), вероятно, потому что его тип является общим. Я знаю, что есть Marshal.OffsetOf
, но он возвращает неуправляемое смещение, а не управление.
Как получить это смещение от экземпляра FieldInfo
? Есть ли какой-либо метод .NET, который используется для этого, или я должен написать свой собственный, принимая во внимание все исключения (размер шрифта, заполнение, явные смещения и т. Д.)?
@usr Meant 'Field3'. На самом деле, это изменено, к моему удивлению. Он переместил это поле в конец класса, заполнив его (отладка и выпуск, 32-разрядная версия). Это может иметь какое-то отношение к невозможности получения указателей общих типов. – IllidanS4
Вы не можете узнать, макет управляемых объектов - это деталь реализации. Кроме того, через бэкдор вы уже обнаружили. CLR использует это для оптимизации макета, делая объект как можно меньшим, сохраняя при этом гарантии выравнивания. [StructLayout] соблюдается только в маршалированных структурах. В этом случае Marshal.SizeOf() дает вам смещение. –
@Hans But Marshal.SizeOf возвращает неуправляемый размер шрифта, а не управляемый. Я думал, что LayoutKind.Explicit почитается в структурах, перекрывая поля, являющиеся доказательством этого, без сортировки. – IllidanS4