What is boxing and unboxing in C#, how does is affect performance and how to prevent common programming mistakes?
In simple terms:
Boxing implies storing a value type as an object = box value type in System.Object
Unboxing = read the value from an object = unbox value from the object
Now the official definitions:
1. Boxing
Boxing is the process of converting a value type to the type object or to any interface type implemented by this value type.
.NET CLR boxes a value type i.e., wraps it in System.Object instance and stores it on the managed(garbage-collected) heap.
Boxing is an implicit operation.
2. Unboxing
Unboxing is an explicit conversion from the type object to a value type or from an interface type to a value type that implements the interface.
Unboxing extracts the value type from the object.
An unboxing operation consists of:
i. Checking the object instance to make sure that it is a boxed value of the given value type.
ii. Copying the value from the instance into the value-type variable.
Attempting to unbox null causes a NullReferenceException.
Attempting to unbox a reference to an incompatible value type causes an InvalidCastException.
Boxing and unboxing operations affect the performance as they are computationally expensive processes.
When a value type is boxed, a new object must be allocated and constructed. To a lesser degree, the cast required for unboxing is also expensive computationally.
Below are some common pitfalls during programming that cause boxing/ unboxing unintentionally but will affect the performance in the long run.
Try to avoid these wherever possible:
1. Using the “foreach” loop with a value type
2. Storing value types in collections that are designed for reference types
3. Using the “as” operator with value types
4. Using the “is” operator with value types
5. Using the “object” type as a catch-all for method arguments or return types
6. Using the “lock” statement with value types
7. Using value types as the key in a dictionary
8. Using the “ref” or “out” keywords with value types
9. Using method overloads with value types
10. Using value types in LINQ queries
11. Using the “dynamic” type
12. Using the “object” type as a generic type argument
References:
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/types/boxing-and-unboxing