C# – Why Is There Only a Null-Check in IL Code When Using ‘is’ Operator?

c++il

I was wondering how is is operator implemented in C#.And I have written a simple test program (nothing special, just for demonstration purposes):

class Base
{
    public void Display() {  Console.WriteLine("Base"); }
}

class Derived : Base { }

class Program
{
    static void Main(string[] args)
    {
        var d = new Derived();

        if (d is Base)
        {
            var b = (Base) d;
            d.Display();
        }
    }
}

And looked at the generated IL code:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init ([0] class ConsoleApplication1.Derived d,
           [1] bool V_1,
           [2] class ConsoleApplication1.Base b)
  IL_0000:  nop
  IL_0001:  newobj     instance void ConsoleApplication1.Derived::.ctor()
  IL_0006:  stloc.0  // set derived (d)
  IL_0007:  ldloc.0 // load derived
  IL_0008:  ldnull // push a null reference
  IL_0009:  ceq   // and compare with d !?
  IL_000b:  stloc.1
  IL_000c:  ldloc.1
  IL_000d:  brtrue.s   IL_001a
  IL_000f:  nop
  IL_0010:  ldloc.0
  IL_0011:  stloc.2
  IL_0012:  ldloc.0
  IL_0013:  callvirt   instance void ConsoleApplication1.Base::Display()
  IL_0018:  nop
  IL_0019:  nop
  IL_001a:  ret
} // end of method Program::Main

When I look at the documentation it says:

Pushes a null reference (type O) onto the evaluation stack.

for ldnull. Ofcourse, I wasn't expecting to see a source code here, but I'm surprised that there is only a null-check.I thought it may be relevant with compiler optimizations because Derived derives from Base so there is no check the compatibility about the types.then I check out and see that the optimizations are turned off.when I turn on the optimizations there wasn't even null-check.

So the question is why there is nothing generated about is operator ? why I see only a null-check ? Is it somehow relevant with is operator and I couldn't see ?

Best Answer

The type of d is Derived, which is always of type Base or null. That's why the non-optimized code only checks for null.

The optimized code doesn't do a check at all because the optimizer knows that d is not null (since you assigned a new object to it) and didn't change after the assignment.

Related Question