この
最初に、
LayoutKind.Sequential
パラメーターを使用して
LayoutKind.Sequential
属性でクラスをマークします。 これにより、コンパイラはコードで宣言された順序でアンマネージメモリ内のフィールドを配置します。 その後、
Marshal.OffsetOf
メソッドを使用して、クラスの先頭を基準としたオフセットで反射フィールドをソートします。
テストクラスの例:
[StructLayout(LayoutKind.Sequential)] public class TestClass1 { public int Value1; public string Value2; public bool Value3; }
反映されたフィールドの並べ替えの例:
Type type = typeof(TestClass1); List<FieldInfo> fields = new List<FieldInfo>(type.GetFields()); // foreach (FieldInfo field in fields) Console.WriteLine(field.Name); Console.WriteLine(); // ( ) fields.Sort( delegate(FieldInfo _first, FieldInfo _second) { int first = _first.FieldType.GetHashCode(); int second = _second.FieldType.GetHashCode(); return first.CompareTo(second); } ); foreach (FieldInfo field in fields) Console.WriteLine(field.Name); Console.WriteLine(); // fields.Sort( delegate(FieldInfo _first, FieldInfo _second) { int first = Marshal.OffsetOf(type, _first.Name).ToInt32(); int second = Marshal.OffsetOf(type, _second.Name).ToInt32(); return first.CompareTo(second); } ); foreach (FieldInfo field in fields) Console.WriteLine(field.Name); Console.WriteLine();
どのような場合にこれが必要ですか? 率直に言って、非常にまれです。 順序に応じてコードを記述することはお勧めしませんが、それでも便利な場合に起こります。
- 部分的なシリアル化(ネットワークを介した特定のフィールドの更新、名前による順序付けは、リファクタリング時に副作用を引き起こす可能性があります)
- 他のタイプへのマッピング
- 他の言語へのマッピング
- フィールドがツールキットに表示される順序(視覚的な順序はコードの順序と一致します)