10

I looked around for this and could not find an answer. Say I have this code:

class Command<T> : ICommand<T>
{
    public void Execute(T parameter)
    {
        var isNull = parameter == null;
        // ...
    }
}

T could be any class, even a Nullable<>. Does performing the check above cause boxing if T is a value type? My understanding is that this is the same as calling ReferenceEquals which takes two object arguments, either of which would cause boxing if T was a value type, if I understand correctly.

If the above does cause boxing, is there a more preferred way to do this without causing the box to occur? I know there is default(T) but in the case of int that is 0, and I am looking to see if this value is null without boxing it. Also, I am looking to do this in a way that satisfies both value and reference types.

Mike-E
  • 2,477
  • 3
  • 22
  • 34
  • 1
    Related: [Why can I test a generic for null when it may not be nullable or may not be an object?](https://stackoverflow.com/questions/5080598/why-can-i-test-a-generic-for-null-when-it-may-not-be-nullable-or-may-not-be-an-o), especially E.Lippert's answer [Why can I test a generic for null when it its runtime type might be neither a nullable value type nor a reference type?](https://stackoverflow.com/a/5080924/284240) – Tim Schmelter Feb 08 '18 at 12:56
  • And: [Does a generic function implicitly cast value types to objects when checking for null?](https://stackoverflow.com/q/21343471/397817) – Stephen Kennedy Feb 08 '18 at 12:56
  • By the way, you can simplify your question to: why is this allowed: `bool intIsNull = 1 == null`, which is also perfectly legal (but useless) code. – Tim Schmelter Feb 08 '18 at 13:06

1 Answers1

9

No - at least not in my understanding. If T is a non-nullable value type, the parameter == null check is effectively replaced with false by the JIT compiler; no execution-time check is performed.

This is an optimization that only the JIT-compiler can perform, as the C# compiler only generates one form of code. For example, the IL generated for your sample is:

IL_0000:  ldarg.1
IL_0001:  box        !T
IL_0006:  ldnull
IL_0007:  ceq

That would appear to actually perform the boxing - but I trust a decent JIT compiler to spot that when T is non-nullable, the ceq will always give a false result, and remove the box operation.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    Awesome. An answer from the venerable Mr. Skeet. Cross that off the tech bucket list. :) Thank you for taking the time to answer! – Mike-E Feb 08 '18 at 19:53