25 March, 2015

"HasValue vs null-check" and "Boxing vs Value property"

A few days ago I took part in a discussion about the differences in performance of the popular expressions, that every developer uses almost every day in the code. The subjects of the discussion were the difference between: null checking versus the HasValue property and boxing cast versus Value property. I have never checked what are the differences between them on my own. I heard a lot of gossips about those expressions and so I have decided to look into the structure of the compiled code. To test the compiled code I have used "IL Disassembler" - the tool, which is included in the Visual Studio package. Here are the results of my investigation.

Boxing vs Value property

Firstly, I created a simple console application, which assigned nullabale integer to two different variables. In the first case, the value was boxed and in the second one, I used the Value property. The code of the application is below:

namespace NullableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int? testInt = 0;
            int castValue = (int) testInt;
            int valueProperty = testInt.Value;
        }
    }
}

Next, I have started IL Disassembler and looked into the application assembly. The result was a little bit surprising:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       25 (0x19)
  .maxstack  2
  .locals init ([0] valuetype [mscorlib]System.Nullable`1 testInt)
  IL_0000:  ldloca.s   testInt
  IL_0002:  ldc.i4.0
  IL_0003:  call       instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0)
  IL_0008:  ldloca.s   testInt
  IL_000a:  call       instance !0 valuetype [mscorlib]System.Nullable`1::get_Value()
  IL_000f:  pop
  IL_0010:  ldloca.s   testInt
  IL_0012:  call       instance !0 valuetype [mscorlib]System.Nullable`1::get_Value()
  IL_0017:  pop
  IL_0018:  ret
} // end of method Program::Main

It occurred, that both constructions are replaced by the body of the Value() property. It means that the performance is exactly the same. There are no differences in the execution time of both structures. You can choose the one you prefer.

HasValue vs null-check

As a next step, I have created another console application, which was checking if the nullable variable is a null. I made it in two different ways: by using the classic null-check and then by using the HasValue property. Here is the code of the application:

namespace NullableTest
{
    class Program
    {
        static void Main(string[] args)
        {
            int? testInt = 0;
            if (testInt != null)
            {
                //Do something ...
            }
            if (testInt.HasValue)
            {
                //Do something else ...
            }
        }
    }
}
.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       25 (0x19)
  .maxstack  2
  .locals init ([0] valuetype [mscorlib]System.Nullable`1 testInt)
  IL_0000:  ldloca.s   testInt
  IL_0002:  ldc.i4.0
  IL_0003:  call       instance void valuetype [mscorlib]System.Nullable`1::.ctor(!0)
  IL_0008:  ldloca.s   testInt
  IL_000a:  call       instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue()
  IL_000f:  pop
  IL_0010:  ldloca.s   testInt
  IL_0012:  call       instance bool valuetype [mscorlib]System.Nullable`1::get_HasValue()
  IL_0017:  pop
  IL_0018:  ret
} // end of method Program::Main

And another surprise! Both constructions are replaced by the body of the HasValue property. Once again it means that the performance is exactly the same and you can choose the one you prefer.

Honestly, I was surprised by the results of the investigation and I can say only one thing: if we are not sure how the code will look after compilation, let's check it using disassebler. After that we will be able to tell exactly what code is a real result of our work and there won't be any discussions about performance... at least in those two cases :)

0 comments:

Post a Comment