Underappreciated C# Struct

Skilled enterprise developers doesn’t use structs in their code. — Copying struct data because of pass-by-value can outweigh performance improvement we gained by avoiding heap allocation — .
How much truth is there ?

If you look at the Common Intermediate Language code of the snippet above, immediately noticed the difference in allocation.
In case of struct, we find an initobj instruction:
IL_0001: ldloca.s sd
IL_0003: initobj SomeStruct
Memory region under address taken from evaluation stack is initialized as “SomeStruct” (initialized each field of the value type at a specific address to a null reference or a 0).
In case of class, we find a newobj instruction:
IL_0009: newobj instance void SomeClass::.ctor()
Allocator is being called creating a new instance of “SomeClass” object and the reference to it is pushed onto the evaluation stack.

Struct allocation is faster since it uses usually only the stack.
Another advantage is about memory consumption. Class allocation uses more space since it puts type information for Garbage Collector along the data itself.
Furthermore, small struct data (usually less than 24 bytes) may be nicely optimized by the JIT compiler to use only CPU registers.
These aspects make using struct seriously considerable when writing data intense and performance oriented code and becomes crucial when operations number or amount of data grows considerably
Immutability enhanced
Anyway, struct downside is his wrong usage. Noteworthy points can be summarized in:
- Copy-by-value semantics: poor performance of data copying when used as method parameters.
- Behavioral limitations: no inheritance is possible.
- Fields assignment when passing around your object: One may have the impression that modifying it will modify its original value.
Best practices to use struct data may help in avoiding unexpected behaviors, can be summed up in enhancing their usage constraints.
A well-known workaround is based on passing struct data by reference with ref keyword. And, in general, explicitly state that an object should not be modified by making it immutable or emphasizing his immutability.


Garbage Collection impact
Stack allocation doesn’t have Garbage Collection information, data lives as much as the function scope and avoids overhead of managing such type instance by the GC. Structs have a good data locality — we can pack data more dense — and needs less memory than classes.
Those traits make structs relevant when working with caches.


Item has Price class elements. For testing purposes, we are going to insert many Price objects per item to simulate a considerable cache usage while measures the GC timing.


Now let’s modify the Price object and turn it into a struct, we’ll get a quite different result. GC is not a free feature!

Struct-based cache is much more faster than class-based one.
Structures are probably one of the most underestimated elements of C# but their were not invented without a reason, small data structs proves to be very useful in performance oriented tasks.