为什么c#没有联盟?

时间:2010-07-10 05:45:37

标签: c#

我正在努力了解为什么C#没有工会背后的技术细节。我理解使用具有显式结构布局的属性机制可以解决这个问题,我更感兴趣的是为什么它比vanilla union构造更受欢迎。

3 个答案:

答案 0 :(得分:6)

允许联合会破坏.NET的安全性,特别是在涉及托管对象时。

例如(对于32位系统):

union MyUnion
{
    string SomeString; // just a 4 byte pointer
    uint SomeInteger;
}

MyUnion u;

u.SomeInteger = 0x98765432;
// What's u.SomeString? What happens if I try to access it?

C#允许您使用不安全关键字并使用某些属性进行自拍,但从不涉及托管类型。您可能已经注意到FieldOffset不允许您将随机类型组合在一起。尝试使用上面的“联合”。

这是我得到的:

  

无法从中加载“MyUnion”类型   程序集'ConsoleApplication2,   版本= 1.0.0.0,文化=中立,   PublicKeyToken = null'因为它   包含偏移0处的对象字段   不正确的对齐或   由非对象字段重叠。

答案 1 :(得分:4)

因为工会本质上不是类型安全的,也不是指针安全的,CLR非常重视这两者。

请考虑以下事项:

union MyUnion
{
    private List<int> myList;
    private int integer;

    public MyUnion(int foo) { integer = foo; }
    public List<int> List { get { return myList; } }
}

这不仅非常不起作用(特别是在64位平台下),但它也破坏了CLR的许多保证,阅读它会很痛。

首先,它允许您在不实际使用指针的情况下获取指向对象的指针,因此需要对所有联合进行分类unsafe。然后,它还允许您更改此指针,这可能具有非常有趣的含义:例如,如果您不小心将其更改为另一个有效列表的地址,垃圾收集器可能会决定移动此列表,并更改您的值整数而不说。

这也完全是类型不安全的。列表与整数无关;但由于整数看起来像指针,这“并不坏”。现在,请考虑以下示例:

union MyUnion
{
    private List<int> myList;
    private Form myForm;

    public MyUnion(Form theForm) { myForm = theForm; }

    public List<int> List { get { return myList; } }
}

如果你打电话给MyUnion.List.Add(4),现在你的表格会怎样?很明显,崩溃。因为这完全是类型不安全的,但工会让你相信它是安全的。

答案 2 :(得分:1)

如果您可以将引用类型转换为值类型,则可以使用StructLayout(LayoutKind.Explicit)中的ValueWrapper属性。几个星期前我看到了这个提示here