Почему 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
Адрес First = 40F2D4
Адрес NotFirst = 40F2CC
Обратите внимание, что адрес First не совпадает с адресом структуры; однако адрес NotFirst совпадает с адресом структуры.
Теперь закомментируйте поле "DateTime WTF" в структуре и запустите его снова. На этот раз я получаю аналогичный результат:
Адрес struct = 15F2E0
Адрес First = 15F2E0
Адрес NotFirst = 15F2E8
Теперь "Первый" имеет тот же адрес, что и структура.
Я нахожу это поведение неожиданным, учитывая использование LayoutKind.Sequential. Может ли кто-нибудь дать объяснение? Имеет ли такое поведение какие-либо последствия при взаимодействии с структурами C/С++, использующими тип Com DATETIME?
[EDIT] ПРИМЕЧАНИЕ. Я подтвердил, что, когда вы используете Marshal.StructureToPtr() для маршалирования структуры, данные сортируются в правильном порядке с первым полем "Первое". Кажется, это говорит о том, что он будет работать нормально с interop. Тайна заключается в том, почему меняется внутренняя компоновка, но, конечно, внутренняя компоновка никогда не указана, поэтому компилятор может делать то, что ей нравится.
[EDIT2] Удалено "небезопасно" из объявления структуры (это осталось от некоторого тестирования, которое я делал).
[EDIT3] Исходный источник этого вопроса был из форумов MSDN С#: