C# boxing with String concatenation and interpolation
Boxing is evil and you should always try to avoid it. That is what I tell my students in my C# training. But what is boxing and how do you avoid it. Boxing is wrapping a value type (struct) inside a reference type (object or interface) variable.
using System; namespace BoxingDemo { class Program { static void Main(string[] args) { int a = 5; object b = a; // boxing IComparable c = a; // boxing int d = (int)b; // unboxing, also evil (slow) } } }
Boxing is evil because it is “slow”. It creates a reference type (the boxed value) which the garbage collector has to clean up (which is also “slow”). I will first explain how you can detect boxing and then how to avoid it when using string concatenation and interpolation.
Detect boxing and unboxing in IL
You can detect boxing and unboxing by examining the Intermediate Language (IL) which is generated by the compiler. I use the free ILSpy extension for this but there are alternatives like Reflector (paid) and dotPeek (free).
ILSpy shows you the following IL for the program I wrote above. For this you have to select the project in the Solution Explorer and then select the ‘Open output in ILSpy’ from the context menu. In ILSpy you select the Main method and from the dropdown in the toolbar you select ‘IL with C#’.
In ILSpy you see that there is boxing (box instruction) on line 24 and 28 and unboxing (unbox instruction) on line 32.
If you don’t like to install an extra extension you might want to try the website SharpLab.io. SharpLab is a .NET code playground that shows intermediate steps and results of code compilation. It is also very nice.
Detect boxing using the CLR Heap Allocation Analyzer
There is also an easier way to detect boxing. The CLR Heap Allocation Analyzer is an open source Roslyn based C# heap allocation diagnostic analyzer that can detect explicit and many implicit allocations like boxing, display classes, implicit delegate creations, etc. You can install it as a NuGet package or Visual Studio extension.
In the following screenshot you get two compiler warnings due to boxing on line 7 and 8. This is much easier than using ILSpy.
Boxing with string concatenation (+ operator)
You get also boxing if you concatenate a value type to a string. This is caused by the ‘right’ parameter of the + operator method, it is of the type object. The salary gets boxed into an object.
The CLR Heap Allocation Analyzer also shows me a warning (line 8). And in ILSpy you can see on line 23 you have boxing.
If I write the same code in Visual Studio 2019 and examine the IL you get a different result. The 2019 Roslyn compiler has added the ToString() call on line 23 which avoids the boxing. This is way better and faster.
If you are still using Visual Studio 2017 you should add the ToString() call manually to avoid the boxing. As you can see the compiler warning is gone.
Boxing with string interpolation
String interpolation was added to C# 6.0 in 2015. It makes calling String.Format() much easier. Unfortunately, it can cause boxing. Even in Visual Studio 2019. See the code below in which I rewrote the previous code using string interpolation.
On line 23 you get boxing in the call of String.Format() the second parameter is of the type object.
The solution is easy, just use salary.ToString("C2") to convert the value type to a string first (line 8).
In the IL you can see that there is no boxing any more. String.Format() is even not called it uses the faster String.Concat(). This is perfect!
Closure
I hope you like this blog post. C# is a great and fast language but you have to know the quirks. Use analyzers to help you improve your coding skills.
Fons
All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.
Blog comments
Yuriy
10-Jan-2020 2:39Kris
11-Jan-2020 4:57Craig
13-Jan-2020 4:25Nicholas Petersen
14-Jan-2020 12:01Morten
23-Jan-2020 9:56