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