I'm trying to collect all of the situations in which boxing occurs in C#:
Converting value type to
System.Object
type:struct S { } object box = new S();
Converting value type to
System.ValueType
type:struct S { } System.ValueType box = new S();
Converting value of enumeration type to
System.Enum
type:enum E { A } System.Enum box = E.A;
Converting value type into interface reference:
interface I { } struct S : I { } I box = new S();
Using value types in C# string concatenation:
char c = F(); string s1 = "char value will box" + c;
note: constants of
char
type are concatenated at compile timenote: since version 6.0 C#, Roslyn 1.0-beta (>=VS2015 preview) compiler optimizes concatenation involving
bool
,char
,IntPtr
,UIntPtr
typesnote: since Roslyn 3.3 compiler (>=VS2019.3) value types are first converted to string and then concatenated, hence no boxing (same applies for string interpolation in .Net6)
Creating delegate from value type instance method:
struct S { public void M() {} } Action box = new S().M;
Calling non-overridden virtual methods on value types:
enum E { A } E.A.GetHashCode();
Using C# 7.0 constant patterns under
is
expression:int x = …; if (x is 42) { … } // boxes both 'x' and '42'!
Boxing in C# tuple types conversions:
(int, byte) _tuple; public (object, object) M() { return _tuple; // 2x boxing }
Optional parameters of
object
type with value type default values:void M([Optional, DefaultParameterValue(42)] object o); M(); // boxing at call-site
Checking value of unconstrained generic type for
null
:bool M<T>(T t) => t != null; string M<T>(T t) => t?.ToString(); // ?. checks for null M(42);
note: this may be optimized by JIT in some .NET runtimes
Type testing value of unconstrained or
struct
generic type withis
/as
operators:bool M<T>(T t) => t is int; int? M<T>(T t) => t as int?; IEquatable<T> M<T>(T t) => t as IEquatable<T>; M(42);
note: this may be optimized by JIT in some .NET runtimes
Are there any more situations of boxing, maybe hidden, that you know of?
private int? nullableInteger
– Indulgencechar.ToString
) and 7th (enum.GetHashCode
) cause boxing! Great tip, and worst gotcha if it's true.. – CribEnum.HasFlag
doesn't box I believe: blogs.msdn.microsoft.com/dotnet/2018/04/18/…. While I could seebox
instruction in IL still in 2.1 app, it doesn't allocate, hence I dont see the perf penalty. – Crib