Unions in .NET
A lot of my .NET research time has been learning ilasm and CIL. It's given me a better perspective on .NET-related issues, and there's one idea that I'd like to discuss: unions. Now, a union is a structure where you can store more than one field into the same storage area. For example, here's a very simple union in C:
union mixed
{
char c;
float f;
int i;
}
Note: bonus points goes to the first person who can correctly identify the book that I pulled this example from.
Now, there is no union-related keyword in both C# and VB.NET. There is a way you can declare them, though, but first I'm going to show you what unions look like in CIL:
assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
.ver 1:0:37500:0
}
.assembly UnionTest
{
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module UnionTest.dll
.namespace UnionTest
{
.class public sealed explicit SampleUnion
extends [mscorlib]System.ValueType
{
.field [0] public float32 FloatValue
.field [0] public int32 IntValue
.field [0] public unsigned int8 ByteValue
}
.class public sealed explicit SampleObjectUnion
extends [mscorlib]System.ValueType
{
.field [0] public string StringValue
.field [0] public object ObjectValue
}
}
While you may have never looked at ilasm before, you should be able to read this and get a good feel for what's going on. I've declared two value types, SampleUnion and SampleObjectUnion
They extend System.ValueType so they can't be used as a base type
The type is declared with the explicit attribute, which is used to obtain precise layout control of the type's fields
Each field is declared using the same field slot
If you would compile this CIL via ilasm to produce an assembly, you could use the unions in any .NET language. Here's a code snippet of a C# application using both types:
using UnionTest
SampleValueUnion svu;
svu.ByteValue = 44;
svu.IntValue = 222222;
svu.FloatValue = 222222.222F;
SampleReferenceUnion sru;
sru.StringValue = "Here's a string value.";
sru.ObjectValue = new System.Collections.Queue();
Now, you may have wondered why I had two different unions in UnionTest. Take a good look at the types within the unions. The types within SampleValueUnion are all value types, and SampleReferenceUnion contains all reference types. Let's say I tried to do this:
.class public sealed explicit SampleUnion
extends [mscorlib]System.ValueType
{
.field [0] public float32 FloatValue
.field [0] public int32 IntValue
.field [0] public unsigned int8 ByteValue
.field [0] public string StringValue
.field [0] public object ObjectValue
}
It would compile, but I'd get a TypeLoadException when I would try to use it. You can't have both value and reference types in the same field array slot in a union.
As I mentioned before, unions can be declared in C# and VB.NET. However by using the StructLayoutAttribute and FieldOffsetAttribute attributes on a value type. Here's what SampleValueType looks like in VB.NET:
Imports System.Runtime.InteropServices
< StructLayout( LayoutKind.Explicit )> _
Public Structure SampleUnion
< FieldOffset( 0 )> Public FloatValue As Single
< FieldOffset( 0 )> Public IntValue As Integer
< FieldOffset( 0 )> Public ByteValue As Byte
End Structure
Of course, if both C# and VB.NET had a union keyword, this declaration would be easier to make and read:
Public Union SampleUnion
Public FloatValue As Single
Public IntValue As Integer
Public ByteValue As Byte
End Structure
Given the fact that you can choose what fields go into which field slots, the syntax may need some tweaking:
Public Union SampleUnion
Public (0) FloatValue As Single
Public (0) IntValue As Integer
Public (1) ByteValue As Byte
Public (1) DoubleValue As Double
End Structure
However, I'll leave syntax issues up to the designers of C# and VB.NET if they add unions in a future version. Also, unions are not CLS-compliant, so be careful with your designs if you decide to use them.
By the way, this is a great example showing the power of attributes in .NET. Even though the languages do not explicitly support the declaration of unions with a keyword, you can still create them with metadata.
I hope this article has given you some insight into an aspect of .NET that you may not have been aware of. I encourage you to spend some time learning the base language of .NET: CIL. It'll enhance your understanding of how .NET really works.