Почему LayoutKind.Sequential работает иначе, если структура содержит поле DateTime?

Почему LayoutKind.Sequential работает иначе, если структура содержит поле DateTime?

Рассмотрим следующий код (консольное приложение, которое должно быть скомпилировано с включенным "небезопасным"):

using System;
using System.Runtime.InteropServices;

namespace ConsoleApplication3
{
    static class Program
    {
        static void Main()
        {
            Inner test = new Inner();

            unsafe
            {
                Console.WriteLine("Address of struct   = " + ((int)&test).ToString("X"));
                Console.WriteLine("Address of First    = " + ((int)&test.First).ToString("X"));
                Console.WriteLine("Address of NotFirst = " + ((int)&test.NotFirst).ToString("X"));
            }
        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Inner
    {
        public byte First;
        public double NotFirst;
        public DateTime WTF;
    }
}

Теперь, если я запустите приведенный выше код, и я получу следующий результат:

Адрес struct = 40F2CC
Адрес первого лица = 40F2D4
Адрес NotFirst = 40F2CC

Обратите внимание, что адрес First НЕ совпадает с адресом структуры; однако адрес NotFirst совпадает с адресом структуры.

Теперь закомментируйте поле «DateTime WTF» в структуре и запустите его снова. На этот раз я получаю примерно такой результат:

Адрес структуры = 15F2E0
Адрес первого лица = 15F2E0
Адрес NotFirst = 15F2E8

Теперь «Первый» действительно имеет тот же адрес, что и структура.

Я нахожу такое поведение удивительным, учитывая использование LayoutKind.Sequential. Кто-нибудь может дать объяснение? Имеет ли такое поведение какие-либо последствия при взаимодействии со структурами C / C ++, которые используют тип Com DATETIME?

[РЕДАКТИРОВАТЬ] ПРИМЕЧАНИЕ. Я проверил, что при использовании Marshal.StructureToPtr () для маршалинга структуры данные упорядочиваются в правильном порядке, причем поле «Первое» является первым. Похоже, это говорит о том, что он будет нормально работать с interop. Загадка заключается в том, почему изменяется внутренняя компоновка - но, конечно, внутренняя компоновка никогда не указывается, поэтому компилятор может делать то, что ему нравится.

[EDIT2] Удалено слово «небезопасно» из объявления структуры (оно осталось от некоторых тестов, которые я проводил).

[EDIT3] Первоначальный источник этого вопроса был взят с форумов MSDN C #:

http://social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/fb84bf1d-d9b3-4e91- 823e-988257504b30

21
задан Matthew Watson 9 November 2010 в 14:16
поделиться