2010-07-10 45 views
4

我想了解爲什麼C#沒有工會的技術背後。我明白,使用具有顯式結構佈局的屬性機制可以做到這一點,我更感興趣的是爲什麼它比vanilla union結構更受歡迎。爲什麼c#沒有union?

+0

工會SomeUnion {串SomeStringPointer; IntPtr PointerValue; } SomeUnion u; u.PointerValue = new IntPtr(0x98765432); Console.WriteLine(u.SomeStringPointer); – wj32 2010-07-10 05:48:23

+0

@ wj32這個代碼編譯? – Fanatic23 2010-07-10 05:51:12

+0

該評論意思是不言自明的:)沒關係,我發佈了一個正確的答案。 – wj32 2010-07-10 05:52:36

回答

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,文化=中立, 公鑰=空',因爲它 包含一個對象字段偏移0 錯誤對齊或 重疊非對象字段。

+0

實際上,您可以使用顯式佈局和重疊字段偏移對類型系統造成嚴重破壞。運行時會爲不正確的對齊或對象字段與非對象字段的重疊引發類型加載異常,但具有跳過驗證的權限的代碼可以重疊對託管類型的引用。恕我直言,這是不幸的使用LayoutKind.Explicit不需要不安全的關鍵字,因爲它可以產生無法驗證的代碼。 – 2010-07-10 06:13:15

+0

哦,這很有趣!我不知道。 – wj32 2010-07-10 06:20:36

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)?很明顯,崩潰。因爲這是完全類型不安全的,但工會讓你相信它是安全的。

1

如果您可以將參考類型轉換爲值類型,則可以使用ValueWrapper中的StructLayout(LayoutKind.Explicit)屬性。幾周前我看到這個提示here