Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instantiating a variable if null

Tags:

c#

.net

if (x == null) x = new X(); 

versus

x = x ?? new X(); 

which of these two is actually more performant? once compiled do they effectively wind up as the same thing (would x = x; be a NO-OP as a result)?

like image 767
CodeMonkey1313 Avatar asked Feb 06 '11 19:02

CodeMonkey1313


People also ask

Can we initialize int variable with null in Java?

An int can't be null .

Why do we initialize variables as null in Java?

You should initialize your variables at the top of the class or withing a method if it is a method-local variable. You can initialize to null if you expect to have a setter method called to initialize a reference from another class.

Can we assign null to VAR?

you cannot assign null to a var type. If you assign null the compiler cannot find the variable you wanted in var place. You can assign some empty values.


1 Answers

Looking at the intermediate language code there is a difference:

.method private hidebysig instance void Method1() cil managed {     .maxstack 8     L_0000: ldarg.0      L_0001: ldfld class X Program::x     L_0006: brtrue.s L_0013     L_0008: ldarg.0      L_0009: newobj instance void X::.ctor()     L_000e: stfld class X Program::x     L_0013: ret  }  .method private hidebysig instance void Method2() cil managed {     .maxstack 8     L_0000: ldarg.0      L_0001: ldarg.0      L_0002: ldfld class X Program::x     L_0007: dup      L_0008: brtrue.s L_0010     L_000a: pop      L_000b: newobj instance void X::.ctor()     L_0010: stfld class X Program::x     L_0015: ret  } 

Here's the code I compiled to get this:

void Method1() {     if (x == null) x = new X(); }  void Method2() {     x = x ?? new X(); } 

To be sure which is faster you should time both.

 Method     Initial condition   Iterations per second --------------------------------------------------- NullCheck  x is null           33 million   Coalesce   x is null           33 million NullCheck  x is not null       40 million Coalesce   x is not null       33 million 

Conclusion:

  • They are about the same in this case where the value is initially null.
  • The method using an if statement is considerably faster than the null coalescing operator when x is already not null.

The difference when x is not null looks like it might be due to the null coalescing operator assigning the value of x back to x (stfld in IL), whereas the null check jumps over the stfld instruction when x is not null.

Both are so fast that you'd have to have a very tight loop to notice the difference. You should only make these sorts of performance optimizations if you have profiled your code with your data. Different situations, different versions of .NET, different compilers, etc. may produce different results.

In case someone wants to know how I got these results or reproduce them, here's the code I used:

using System;  class X { }  class Program {     private X x;      private X xNull = null;     private X xNotNull = new X();      private void Method1Null()     {         x = xNull;         if (x == null) x = xNotNull;     }      private void Method2Null()     {         x = xNull;         x = x ?? xNotNull;     }      private void Method1NotNull()     {         x = xNotNull;         if (x == null) x = xNotNull;     }      private void Method2NotNull()     {         x = xNotNull;         x = x ?? xNotNull;     }      private const int repetitions = 1000000000;      private void Time(Action action)     {         DateTime start = DateTime.UtcNow;         for (int i = 0; i < repetitions; ++i)         {             action();         }         DateTime end = DateTime.UtcNow;         Console.WriteLine(repetitions / (end - start).TotalSeconds);     }      private void Run()     {         Time(() => { Method1Null(); });         Time(() => { Method2Null(); });         Time(() => { Method1NotNull(); });         Time(() => { Method2NotNull(); });         Console.WriteLine("Finished");         Console.ReadLine();     }      private static void Main()     {         new Program().Run();     } } 

Disclaimer: No benchmark is perfect, and this bechmark is far from perfect, mainly to keep things simple. I've run numerous different tests e.g. with the methods in a different order, with and without "warming up" first, over different lengths of time, etc. I get roughly the same results each time. I didn't have anything to prove one way or the other so any bias favoring one method or the other is accidental.

like image 83
Mark Byers Avatar answered Sep 20 '22 07:09

Mark Byers