0

I have next expression :

var max = items.FirstOrDefault(x => x.Key > date).Value;

if (max == null)
{
    max = items.FirstOrDefault(x => x.Key < date).Value;
}

I would like to shorten it this way :

var max = 
    items.FirstOrDefault(x => x.Key > date).Value ?? // this line
    items.FirstOrDefault(x => x.Key < date).Value;   

And here is the question : is C# smart enough to not execute line before ternary operator twice?

In other words, I hope that ternary operator will not be converted to something like this :

var max = 
    items.FirstOrDefault(x => x.Key > date).Value == null ?
    items.FirstOrDefault(x => x.Key > date).Value : 
    items.FirstOrDefault(x => x.Key < date).Value;
Anonymous
  • 1,823
  • 2
  • 35
  • 74
  • 1
    Why shorten it? It hurts readability and in this case may even introduce unknown behavior. As c# is compiled down, it doesn't matter if it is slightly verbose and so I see no reason to move away from the code as written. It is a micro optimization and will just end up wasting time in the form of finding this type of code to "optimize" or in the form of troubleshooting this behavior at a later time. – Travis J May 29 '15 at 22:47
  • @Travis : Resharper told me to do that ... I have to, it forces me to do that displaying ugly underscore under IF :) – Anonymous May 29 '15 at 22:50
  • 1
    See phoog's answer.Your second sample is correct and it does not compile into the third – George Vovos May 29 '15 at 22:54
  • @TravisJ : I have to disagree, the ??-operator is much more readable and verbose than the first code. I actually recommend putting the ?? on the newline (as with the ? and : in ternary operators). – crazy_crank May 29 '15 at 22:55
  • @crazy_crank - You know what verbose means, right? – Travis J May 29 '15 at 22:58
  • @crazy_crank The conditional operator version of the expression has a performance penalty, which could be significant if `items` contains a large number of, well, items. You could keep the conditional operator and get rid of the performance penalty by storing the result of the "greater than" query in a variable. That would add yet another line of code, increasing verbosity. Verbosity is generally regarded as a bad thing. It would, however, make the code less repetitive. – phoog May 29 '15 at 23:00
  • @TravisJ yes I know, and I wanted to write concise, thank you :) – crazy_crank May 29 '15 at 23:05
  • @phoog I totally agree, I was only talking about the code style – crazy_crank May 29 '15 at 23:06

1 Answers1

3

Your terminology is off. The ?? operator is the null coalescing operator. The ternary operator is actually the second, the conditional operator: condition ? expression1 : expression2.

The null coalescing operator is not compiled into a ternary conditional expression. It is explicitly specified as a short-circuiting operator.

From the C# specification:

A null coalescing expression of the form a ?? b requires a to be of a nullable type or reference type. If a is non-null, the result of a ?? b is a; otherwise, the result is b. The operation evaluates b only if a is null.

By contrast, the conditional operator in your example risks executing the "greater than" query twice. It is described thus:

A conditional expression of the form b ? x : y first evaluates the condition b. Then, if b is true, x is evaluated and becomes the result of the operation. Otherwise, y is evaluated and becomes the result of the operation. A conditional expression never evaluates both x and y.

phoog
  • 42,068
  • 6
  • 79
  • 117
  • 1
    My bad, sorry, changed the title. The key of the question is that will "a" be executed twice if it is true? I mean, first time it will be executed to check the expression for null and second time to get actual value, or it will execute "a", remember result of "a", check it for null and if it is not then will use remembered value? – Anonymous May 29 '15 at 22:55
  • Somebody pointed that there is a similar question that answers mine, thanks for clarification on execution sequence - http://stackoverflow.com/questions/29554773/does-null-coalescing-operator-cache-the-result-in-c-sharp – Anonymous May 29 '15 at 23:03