如果一个结构体包含 DateTime 字段,为什么 LayoutKind.Sequential 的工作方式会有所不同?
考虑以下代码(必须启用“不安全”编译的控制台应用程序):
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;
}
}
现在,如果我运行上面的代码,我会得到类似以下的输出:
结构体的地址 = 40F2CC First 的地址 = 40F2D4 NotFirst 的地址 = 40F2CC
请注意,First 的地址与结构体的地址不同;但是,NotFirst 的地址与结构体的地址相同。
现在注释掉结构体中的 "DateTime WTF" 字段,然后再次运行它。 这一次,我得到类似以下的输出:
结构体的地址 = 15F2E0 First 的地址 = 15F2E0 NotFirst 的地址 = 15F2E8
现在,"First" 的地址与结构体相同。
考虑到使用了 LayoutKind.Sequential,我发现这种行为令人惊讶。有人能提供解释吗?在与使用 Com DATETIME 类型的 C/C++ 结构体进行互操作时,这种行为是否有任何影响?
[编辑] 注意:我已经验证当您使用 Marshal.StructureToPtr() 将结构体编组时,数据以正确的顺序编组,"First" 字段排在第一位。这似乎表明它将与互操作正常工作。谜团是为什么内部布局会改变 - 但当然,内部布局从未被指定,所以编译器可以随心所欲。
[编辑2] 从结构声明中删除 "unsafe"(它是我进行一些测试时留下的)。
[编辑3] 这个问题的原始来源是来自 MSDN C# 论坛: