Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does c# not have union?

Tags:

c#

I am trying to understand the technicalities behind why C# does not have unions. I understand that using the attribute mechanism with explicit structure layout does the trick, I am more interested in why this was preferred over vanilla union construct.

like image 668
Fanatic23 Avatar asked Dec 23 '22 01:12

Fanatic23


2 Answers

Allowing unions would undermine the safety of .NET, especially when it comes to managed objects.

For example (for 32-bit systems):

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# does allow you to shoot yourself in the foot with the unsafe keyword and with certain attributes, but never involving managed types. You might have noticed that FieldOffset doesn't let you combine random types together. Try it with the above "union".

Here's what I get:

Could not load type 'MyUnion' from assembly 'ConsoleApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.

like image 195
wj32 Avatar answered Jan 09 '23 08:01

wj32


Because unions are inherently not type-safe nor pointer-safe, and the CLR puts great emphasis over both.

Consider the following:

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

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

Not only this can very much not work (notably under a 64 bits platform), but it also breaks so many guarantees of the CLR that it hurts to read it.

First, it allows you to get the pointer to the object without actually using pointers, so unions would all need to be classified unsafe. Then, it also lets you change this pointer, which can have very funny implications: for instance, if you accidentally change it to the address of another valid list, the garbage collector might decide to move this list around, and change the value of your integer without telling.

This is also completely type-unsafe. Lists have nothing to do with integers; but since integers look like pointers, this is "not that bad". Now, consider the following example:

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

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

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

Now what is that gonna do with your form if you call MyUnion.List.Add(4)? Much obviously, crash. Because this is completely type-unsafe, but unions let you believe it's safe.

like image 41
zneak Avatar answered Jan 09 '23 08:01

zneak