Search code examples
c#timingnull-coalescing-operator

?? and || Operator timing


I am starting to learn C# and have just started using the ?? operator, but am slightly confused about the timing. Take the below code example:

    string x = null;
    string y = null;
    string v = null;

    var watch = System.Diagnostics.Stopwatch.StartNew();

    if (string.IsNullOrEmpty(x ?? y ?? v ?? y ?? v))
    {

    }

    watch.Stop();
    var elapsedMs = watch.ElapsedTicks;
    Console.WriteLine(elapsedMs.ToString());

    watch.Restart();

    if (string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y) || string.IsNullOrEmpty(v) || string.IsNullOrEmpty(y) || string.IsNullOrEmpty(v))
    {

    }

    var elapsedMs2 = watch.ElapsedTicks;
    Console.WriteLine(elapsedMs2.ToString());

The result i get is that the first if statement takes around 100 ticks whilst the second usually around 3. I was under the impression that both of these would be similar in timing, or that the second if statement with the || would take longer.

Obviously i am missing something here. I thought that after the first x was evaluated to null that would be it and the rest wouldn't be evaluated. Is anyone able to explain what i am getting wrong here?


Solution

  • Do you maybe have the definition of ?? backward? a ?? b means:

    • If a is null, b
    • Otherwise, a

    So if the left side is not null, then we don't evaluate b, since we know a ?? b is a. If a is null, as in your case, we do have to evaluate b.

    if (string.IsNullOrEmpty(x ?? y ?? v ?? y ?? v))

    runs as:

    • Evaluate x.
    • That evaluates as null, so evaluate y.
    • That evaluates as null, so evaluate v.
    • That evaluates as null, so evaluate y.
    • That evaluates as null, so evaluate v.
    • That evaluates as null. Pass this value (null) into string.IsNullOrEmpty.
    • That evaluates as true. Enter the block.

    if (string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y) || string.IsNullOrEmpty(v) || string.IsNullOrEmpty(y) || string.IsNullOrEmpty(v))

    evaluates as:

    • Evaluate x.
    • That evaluates as null. Pass this value (null) into string.IsNullOrEmpty.
    • That evaluates as true. Since || is satisfied if only one of the sides is true, we do not evaluate the right side of the first ||, or any further to the right. Enter the block.