構造体に 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」フィールドが最初になることを確認しました。これは、相互運用性で問題なく動作することを示唆しているようです。内部レイアウトが変更される理由は謎ですが、もちろん、内部レイアウトは指定されていないため、コンパイラは好きなことを行うことができます。
[EDIT2]構造体宣言から「安全でない」を削除しました(私が行っていたいくつかのテストから残っていました)。
[EDIT3] この質問の元のソースは、MSDN C# フォーラムからのものです。