Select Page

ByteUnion – Unions in .NET/C#

Do you ever wonder what happened to the old-school C/C++ unions in C# ?
Unions were extremely usefull for a wide range of problems back in the days where we dared make bold assumptions about memory-layout and the width of variables.

.NET/C# does not allow us to make unions like that directly anymore, but we can still achieve most of the functionality by explicitly controlling the layout of classes and structs in C#

A tiny example

The System.Runtime.InteropServices namespace has the tools to handle the layout of structs and classes. It allows you to define fields in structures in a way so they even overlap.
This mechanism – when used with simple data types – can be used to simulate unions in C#.

Take a look at the following small class:

public class union
    [FieldOffset(0)] public byte lowbyte;
    [FieldOffset(1)] public byte highbyte;
    [FieldOffset(0)] public ushort word;

This is a very basic class containing only two bytes and a word. There are two very interesting things to note though.

  • The whole class is given the “StructLayout(LayoutKind.Explicit)” attribute. This tells the compiler that we want to control the layout of the fields ourselves.
  • Each field is then given an offset with the “FieldOffset” attribute. This is where the magic happens. The 16-bit word is placed so it overlaps the two 8-bit bytes.

Using it…

Now if you assign anything to the 16-bit word it will change the 2 bytes – and vice versa. The class can now be used like this:

union u = new union();
u.word = 0x0102;

Console.WriteLine("lowbyte is: " + u.lowbyte);
Console.WriteLine("highbyte is: " + u.highbyte);

The code will output:

lowbyte is: 2
highbyte is: 1

Practical applications

I have used this class – in an expanded version – in several projects. In EKHO I use it to parse the input from the audio port. The data from that port is a byte-stream that contain pairs of bytes, that represent the 16-bit samples. In a project I have done for a company called Kamstrup, it is used to handle data recieved as byte arrays on a serial port.
Generally – Whenever you have code that says something like “a = x*256 + y” or “b = (arr[0]<<8) + arr[1]" you can use a ByteUnion instead and greatly enhance readability.

Additional functionality

The ByteUnion class I have used in real-life projects is much more advanced than this tiny example. The real power of the class is only really obvious when the class is expanded with a constructor that take a byte array as an argument. Also adding stuff like comparison operators and a few interfaces really enhance the usability.
I will return with that in a later post… Now I have work to do 🙂