C#StructLayout.Explicit问题

我试图理解为什么下面的第二个例子没有问题,但第一个例子给了我下面的例外。 在我看来,两个例子都应该基于描述给出例外。 任何人都可以开导我吗?

未处理的exception:System.TypeLoadException:无法从程序集’StructTest,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null’加载类型’StructTest.OuterType’,因为它包含偏移0处的对象字段,该字段未正确对齐或重叠由非对象字段。
在StructTest.Program.Main(String [] args)按任意键继续。 。 。

例1

using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace StructTest { [StructLayout(LayoutKind.Sequential, Pack = 1)] struct InnerType { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] char[] buffer; } [StructLayout(LayoutKind.Explicit)] struct OuterType { [FieldOffset(0)] int someValue; [FieldOffset(0)] InnerType someOtherValue; } class Program { static void Main(string[] args) { OuterType t = new OuterType(); System.Console.WriteLine(t); } } } 

例2

 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace StructTest { [StructLayout(LayoutKind.Sequential, Pack = 1)] struct InnerType { [MarshalAs(UnmanagedType.ByValArray, SizeConst = 100)] char[] buffer; } [StructLayout(LayoutKind.Explicit)] struct OuterType { [FieldOffset(4)] private int someValue; [FieldOffset(0)] InnerType someOtherValue; } class Program { static void Main(string[] args) { OuterType t = new OuterType(); System.Console.WriteLine(t); } } } 

公共语言运行库包含一个validation程序,用于确保正在运行的代码(可validation的IL)不可能破坏托管环境中的内存。 这可以防止您声明字段重叠的结构。 基本上,您的struct包含两个数据成员。 一个整数(4个字节)和本机整数(指针大小)。 在32位CLR上,你可能正在运行你的代码, char[]将占用4个字节,所以如果你把整数小于4字节远离结构的开头,你将有重叠的字段。 有趣的是,由于指针大小为8字节,因此两个代码片段在64位运行时都会失败。

我想我会用我用来创建联合的解决方案做出回应 – 这是我的初衷。 我使用了一个不安全的结构和一个固定数组,然后使用一个属性与固定数组进行交互。 我相信这应该做我想要的。

 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; namespace StructTest { [StructLayout(LayoutKind.Explicit)] unsafe struct OuterType { private const int BUFFER_SIZE = 100; [FieldOffset(0)] private int transactionType; [FieldOffset(0)] private fixed byte writeBuffer[BUFFER_SIZE]; public int TransactionType { get { return transactionType; } set { transactionType = value; } } public char[] WriteBuffer { set { char[] newBuffer = value; fixed (byte* b = writeBuffer) { byte* bptr = b; for (int i = 0; i < newBuffer.Length; i++) { *bptr++ = (byte) newBuffer[i]; } } } get { char[] newBuffer = new char[BUFFER_SIZE]; fixed (byte* b = writeBuffer) { byte* bptr = b; for (int i = 0; i < newBuffer.Length; i++) { newBuffer[i] = (char) *bptr++; } } return newBuffer; } } } class Program { static void Main(string[] args) { OuterType t = new OuterType(); System.Console.WriteLine(t); } } }