On structs: an underutilized part of C#
The 2014 book Writing High-Performance .NET Code contains tips on coding effective C#, above and beyond the Zen of Performance. It made me consider the usage of value types, struct
instead of class
.
By using struct
for small structures, we achieve less memory usage, better memory locality and fewer garbage collections. Arrays of structs have good memory locality, utilising the CPU caches and improving performance due to more cache hits.
Design guidelines
As all other value types in C#, your structs should be immutable. Set your fields and properties
readonly
and create custom constructors. As structs can always be constructed using the default constructor, the default values for all fields and properties must make sense in your context.Implement
IEquatable<T>
. The defaultEquals
implementation uses reflection and boxing and should be avoided. Also overridebool Equals(object obj)
andint GetHashCode()
.Keep them small, Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries suggests under 16 bytes. Since value types are copied unless passed by reference (
ref
), performance will degrade if thestruct
becomes too big. C# classes have a pointer size of 4 bytes, 8 bytes for x64 applications, and an overhead of 8 bytes. Structs are just as big as the data they contain. Below are a table of the sizes of the built in value types:
Type | Size |
---|---|
sizeof(sbyte) | 1 |
sizeof(byte) | 1 |
sizeof(short) | 2 |
sizeof(ushort) | 2 |
sizeof(int) | 4 |
sizeof(uint) | 4 |
sizeof(long) | 8 |
sizeof(ulong) | 8 |
sizeof(char) | 2 |
sizeof(float) | 4 |
sizeof(double) | 8 |
sizeof(decimal) | 16 |
sizeof(bool) | 1 |
Recommendation
Use a struct
when:
- The data fits together logically as a single entity
- It will have a small size
- It will be immutable
- It will not be used often in a way that will cause boxing
For all else, use class
.