Почему 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 #: