Układ typu wartości .NET w pamięci

Mam następujące typy wartości .NET:

[StructLayout(LayoutKind.Sequential)]
public struct Date
{
    public UInt16 V;
}

[StructLayout(LayoutKind.Sequential)]
public struct StringPair
{
    public String A;
    public String B;
    public String C;
    public Date D;
    public double V;
}

Mam kod, który przekazuje wskaźnik do typu wartości do kodu niezarządzanego, wraz z przesunięciami wykrytymi przez wywołanie System.Runtime.InteropServices.Marshal.OffsetOf. Kod niezarządzany zapełnia datę i podwójne wartości.

Przesunięcia zgłaszane dla struktury StringPair są dokładnie tym, czego oczekiwałbym: 0, 8, 16, 24, 32

W funkcji testowej mam następujący kod:

FieldInfo[] fields = typeof(StringPair).GetFields(BindingFlags.Instance|BindingFlags.Public);

for ( int i = 0; i < fields.Length; i++ )
{
    int offset = System.Runtime.InteropServices.Marshal.OffsetOf(typeof(StringPair), fields[i].Name).ToInt32();

    Console.WriteLine(String.Format(" >> field {0} @ offset {1}", fields[i].Name, offset));
}

Który drukuje dokładnie te przesunięcia.

 >> field A @ offset 0
 >> field B @ offset 8
 >> field C @ offset 16
 >> field D @ offset 24
 >> field V @ offset 32

Następnie mam jakiś kod testowy: foreach (para StringPair w parach) {Data d = pair.D; double v = pair.V; ...

Z którym debuggerem powiązany jest następujący asembler:

               Date d = pair.D;
0000035d  lea         rax,[rbp+20h] 
00000361  add         rax,20h 
00000367  mov         ax,word ptr [rax] 
0000036a  mov         word ptr [rbp+000000A8h],ax 
00000371  movzx       eax,word ptr [rbp+000000A8h] 
00000378  mov         word ptr [rbp+48h],ax 

                double v = pair.V;
0000037c  movsd       xmm0,mmword ptr [rbp+38h] 
00000381  movsd       mmword ptr [rbp+50h],xmm0 

Ładuje pole D przy przesunięciu 32 (0x20) i polu V przy przesunięciu 24 (0x38-0x20). JIT zmienił porządek. Debuger Visual Studio pokazuje również tę odwróconą kolejność.

Czemu!? Wyciągam włosy, próbując zobaczyć, gdzie moja logika się nie udaje. Jeśli zamieniam kolejność D i V w strukturze, to wszystko działa, ale ten kod musi być w stanie poradzić sobie z architekturą wtyczek, w której inni programiści zdefiniowali strukturę i nie można oczekiwać, że zapamiętają tajemne reguły układu.

questionAnswers(3)

yourAnswerToTheQuestion