C++ union in C#

C#C++Unions

C# Problem Overview


I'm translating a library written in C++ to C#, and the keyword 'union' exists once. In a struct.

What's the correct way of translating it into C#? And what does it do? It looks something like this;

struct Foo {
    float bar;

    union {
        int killroy;
        float fubar;
    } as;
}

C# Solutions


Solution 1 - C#

You can use explicit field layouts for that:

[StructLayout(LayoutKind.Explicit)] 
public struct SampleUnion
{
    [FieldOffset(0)] public float bar;
    [FieldOffset(4)] public int killroy;
    [FieldOffset(4)] public float fubar;
}

Untested. The idea is that two variables have the same position in your struct. You can of course only use one of them.

More informations about unions in struct tutorial

Solution 2 - C#

You can't really decide how to deal with this without knowing something about how it is used. If it is merely being used to save space, then you can ignore it and just use a struct.

However that is not usually why unions are used. There two common reasons to use them. One is to provide 2 or more ways to access the same data. For instance, a union of an int and an array of 4 bytes is one (of many) ways to separate out the bytes of a 32 bit integer.

The other is when the data in the struct came from an external source such as a network data packet. Usually one element of the struct enclosing the union is an ID that tells you which flavor of the union is in effect.

In neither of these cases can you blindly ignore the union and convert it to a struct where the two (or more) fields do not coincide.

Solution 3 - C#

In C/C++ union is used to overlay different members in the same memory location, so if you have a union of an int and a float they both use the same 4 bytes of memory to store, obviously writing to one corrupts the other (since int and float have different bit layout).

In .Net Microsoft went with the safer choice and didn't include this feature.

EDIT: except for interop

Solution 4 - C#

If you're using the union to map the bytes of one of the types to the other then in C# you can use BitConverter instead.

float fubar = 125f; 
int killroy = BitConverter.ToInt32(BitConverter.GetBytes(fubar), 0);

or;

int killroy = 125;
float fubar = BitConverter.ToSingle(BitConverter.GetBytes(killroy), 0);

Solution 5 - C#

Personally, I would ignore the UNION all together and implement Killroy and Fubar as separate fields

public struct Foo
{
    float bar;
    int Kilroy;
    float Fubar;
}

Using a UNION saves 32 bits of memory allocated by the int....not going to make or break an app these days.

Solution 6 - C#

You could write a simple wrapper but in most cases just use an object it is less confusing.

    public class MyUnion
    {
        private object _id;
        public T GetValue<T>() => (T)_id;
        public void SetValue<T>(T value) => _id = value;
    }

Solution 7 - C#

public class Foo
{
    public float bar;
    public int killroy;

    public float fubar
    {
        get{ return (float)killroy;}
        set{ killroy = (int)value;}
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionViktor ElofssonView Question on Stackoverflow
Solution 1 - C#Armin RonacherView Answer on Stackoverflow
Solution 2 - C#Steve FallowsView Answer on Stackoverflow
Solution 3 - C#NirView Answer on Stackoverflow
Solution 4 - C#Steve LillisView Answer on Stackoverflow
Solution 5 - C#ckramerView Answer on Stackoverflow
Solution 6 - C#Kenneth ParkerView Answer on Stackoverflow
Solution 7 - C#Yan ChenView Answer on Stackoverflow