如果结构包含 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;
}
}
现在,如果我运行上面的代码,我会得到类似于以下内容的输出:
struct 的地址 = 40F2CC
First 的地址 = 40F2D4 NotFirst
的地址 = 40F2CC
注意 First 的地址与结构体的地址不同;但是,NotFirst的地址与结构的地址相同。
现在注释掉结构中的“DateTime WTF”字段,然后再次运行它。这一次,我得到类似这样的输出:
struct 的地址 = 15F2E0
First 的地址 = 15F2E0 NotFirst
的地址 = 15F2E8
现在“First”确实与结构具有相同的地址。
考虑到 LayoutKind.Sequential 的使用,我发现这种行为令人惊讶。任何人都可以提供解释吗?与使用 Com DATETIME 类型的 C/C++ 结构进行互操作时,此行为是否有任何影响?
[编辑] 注意:我已经验证,当您使用 Marshal.StructureToPtr() 编组结构时,数据以正确的顺序编组,“First”字段位于第一位。这似乎表明它可以与互操作一起正常工作。奥秘在于为什么内部布局会发生变化——当然,内部布局从来没有被指定,所以编译器可以做它喜欢的事情。
[EDIT2] 从结构声明中删除了“不安全”(它是我正在做的一些测试留下的)。
[EDIT3] 这个问题的原始来源来自 MSDN C# 论坛: