日期:2014-05-18  浏览次数:20801 次

请教:C#的共用体运行出错的疑问?
我定义了一个共用体。如下:
C# code


[StructLayout(LayoutKind.Explicit)]
    public struct MyStruct
    {
        [FieldOffset(0)]
        public UInt32 dwValue;


        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        [FieldOffset(0)]
        public char[] s1;
    }

    MyStruct ms = new MyStruct(); // 运行到这里就会出错,为什么啊?
                                  // 出错信息是:An unhandled exception of type 'System.TypeLoadException'
                                  // occurred in System.Windows.Forms.dll

而如果是把结构体的声明改为:
    public struct MyStruct
    {
        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] bHigh;

        [FieldOffset(64)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
        public byte[] bLow;


        [FieldOffset(0)]
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        public char[] s1;
    }

    就不会出错,这是为什么啊?
    


 

------解决方案--------------------
两个字段都布局到同一个内存里面去了?你这边用了字段内存布局方面的特性 感觉这个东西还是让CLR或者编译器自己去决定的比较好
------解决方案--------------------
没有用结构体模拟过union 所以帮不上忙~
探讨

那我要怎么定义啊?可以给一个例子吗?

------解决方案--------------------
包含引用类型和值类型的结构体,在同一个FieldOffset位置,不能声明成不同的类型
要么都是值类型,要么都是引用类型

C# code

[StructLayout(LayoutKind.Explicit)]
    public struct MyStruct
    {
        [FieldOffset(0)]
        public UInt32? dwValue;


        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        [FieldOffset(0)]
        public char[] s1;
    }

------解决方案--------------------
不好意思,验证了一把,以为可空类型能解决问题,但其实不行,改成
public Object dwValue;
UINT16->Object,不会报错,但不知是否符合楼主要求
------解决方案--------------------
LS的代码没有问题吧~
------解决方案--------------------
报的异常是什么?我用你的代码运行了下没问题 断点去看每个成员也没问题
------解决方案--------------------
在3.5下面编译运行也没问题 结构体声明和你一样 我这样调用尝试了下
var myStruct = new MyStruct();
myStruct.struct1 = new MyStruct1()
{
ucSelectData = new byte[1]
};
MessageBox.Show("hh");
也木有问题~
------解决方案--------------------
关于union msdn上都有,需要声明两次
.NET Framework 开发人员指南
Unions 示例
请参见
 语言筛选器: 全部 语言筛选器: 多个 语言筛选器: Visual Basic 语言筛选器: C# 语言筛选器: C++ 语言筛选器: J# 语言筛选器: JScript
 Visual Basic(声明) 
 Visual Basic(用法) 
 C# 
 C++ 
 J# 
 JScript 

该示例说明如何将两种结构作为参数传递给需要联合的非托管函数,一种结构是只包含值类型的结构,一种结构是同时包含值类型和字符串的结构。联合表示一个可以由两个或多个变量共享的内存位置。Microsoft .NET Framework SDK 在 Samples\Technologies\Interop\Platform-Invoke 目录中包括此示例的完整 Visual Basic 2005 版本和 C# 版本。

Unions 示例使用以下非托管函数(这里同时显示其原始函数声明): 

从 PinvokeLib.dll 导出的 TestUnion。 

复制代码 
void TestUnion(MYUNION u, int type);
 

PinvokeLib.dll 是一个自定义非托管库,它包含前面列出的函数的实现和以下两个联合:MYUNION 和 MYUNION2。这两个联合包含以下元素:

复制代码 
union MYUNION
{
int number;
double d;
}

union MYUNION2
{
int i;
char str[128];
};
 

在托管代码中,将联合定义为结构。MyUnion 结构包含两个值类型作为其成员:一个整型和一个双精度型。StructLayoutAttribute 属性经过设置,以控制每个数据成员的准确位置。FieldOffsetAttribute 属性提供字段在联合的非托管表示形式中的物理位置。请注意,这两个成员具有相同的偏移量值,因此这两个成员可以定义相同的内存块。