I often get asked about the difference in performance characteristics between value types (C# struct) and reference types (C# class or Object).
In the clr, a value type is located on the stack (in a local variable or argument) or within an object. .NET primitive types, such as Int32, Int16, DateTime, double are all value types. Typically, when there is performance issues related to values types it is because of boxing.
Boxing is an implicit conversion of a value type to an object (reference type). Boxing allocates an object from the GC heap and copies the value into it. The cost of boxing is the allocation, the eventual GC of the object and the copy.
Unboxing is the reverse operation that copies the value from the boxed value type to a stack variable.
Rule of thumb: If an object is typically going to get boxed, it would be better off being an Object in the first place.
The other area of performance concern for value types revolve around copying them. The larger the value type, the larger the cost to copy. When is a value type copied?
- Boxing and unboxing
- Assigning from one “home” to another
- Passing a value type argument by value
- new on a value type
So if you are doing enough of any of the above operations on a value type, any value type larger than 32-bits may become more expensive than a corresponding reference type. Where the break-even point is depends on how big the object is, how often it is copied and the overhead of allocating a GC object.
This posting is provided “AS IS” with no warranties, and confers no rights.