In this post I’ll try to deal with few of the myths lying beneath common understanding of how C# structures works in reality. Many of new .NET acolytes are thought about differences between structs and classes. For easier understanding many of those concepts are simplified and therefore doesn’t necessary tell all truth about underlying mechanism.

Here are some of them.

Structs may not be stack allocated

Think about following example:

struct MyStruct
{
     public int X { get; set; }
}

public static Func<int> Example1()
{
    var a = new MyStruct { X = 3 };
    return () =>
    {
        Console.WriteLine(a.X);
        return ++a.X;
    };
}

As you remember, one of the well known side effects of stack-allocated values is that they’re destroyed automatically, when we leave scope, where they were created. This remains true in .NET environment – it assures that no more but one value or pointer may be found on top of the stack when returning from method execution.

But what happens, when we execute Example1 method and then call lambda returned? a variable as stack allocated structure, should be already destroyed at that moment (it’s out of it’s creation scope and has not been returned explicitly). But that’s not what really happens. Actually .NET environment performs an escape analysis to determine if any references to that structure didn’t leave it’s scope. In that case it would be rather heap allocated in order to prevent premature destruction.

Other known case, when structs become heap allocated values, are allocations of large amounts of memory dedicated to handle values. Since stack memory is very limited (by default it’s about 1MB per thread on Windows OS), massive structure allocations would potentially cause a StackOverflowException. What .NET environment does in that case, is fallback to safer heap-based allocations.

NOTE: Unfortunatelly at the present moment C# doesn’t provide escape analysis to determine if class instances could be stack allocated. Java, even though hasn’t got custom value types yet, can provide that feature for specific conditions.

Struct and class method calls differs significantly

Next exercise. Think about two types, struct and a class. Both of them have non-static method with identical signature and implementation. When you create instances of both types and call mentioned methods, which call will be faster? If you’d thought, that struct method call will be slightly faster, you’re right. But why?

Answer lies in low level difference between CIL instructions call and callvirt. Standard class methods use callvirt (name is misleading – it’s used even for non-virtual methods). Since CLR cannot absolutely guarantee, if instance method is overridden or shadowed, it has to perform explicit check by seeking class VTable for function pointer. Actual VTable pointer is one of the internal members of each object. Therefore it requires null check to be performed.

Since struct cannot be null, we don’t have to perform null checking. However it’s not necessary. Since value types cannot declare or override virtual methods – struct have fixed inheritance chain – we don’t have to access their VTables. Actually lack of inheritance is so useful, that structure instances don’t need to have any pointers to VTable at all. All of these save time necessary to perform a method call.

From that perspective struct method calls are much closer to static methods – also invoked through call instruction – than instantiated ones.