我试图理解为什么下面的第二个例子没有问题,但第一个例子给了我下面的例外。在我看来,两个例子都应该基于描述给出例外。谁能开导我?
未处理的例外情况: System.TypeLoadException:无法 从中加载类型'StructTest.OuterType' 程序集'StructTest,版本= 1.0.0.0, Culture = neutral,PublicKeyToken = null' 因为它包含一个对象字段 错误对齐的偏移量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);
}
}
}
答案 0 :(得分:11)
公共语言运行库包含一个验证程序,用于确保正在运行的代码(可验证的IL)不可能破坏托管环境中的内存。这可以防止您声明字段重叠的结构。基本上,您的struct包含两个数据成员。一个整数(4个字节)和本机整数(指针大小)。在32位CLR上,您可能正在运行代码,char[]
将占用4个字节,因此如果您将整数小于4字节远离结构的开头,则您将拥有重叠字段。有趣的是,在64位运行时,两个代码片段都失败,因为指针大小为8个字节。
答案 1 :(得分:1)
我想我会用我用来创建联盟的解决方案做出回应 - 这是我的初衷。我使用了一个不安全的结构和一个固定数组,然后使用一个属性与固定数组进行交互。我相信这应该做我想要的。
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);
}
}
}