1

For example, given this code:

int? ReallyComplexFunction()
{
    return 2; // Imagine this did something that took a while
}

void Something()
{
    int i = ReallyCleverFunction() ?? 42;
}

... is it guaranteed that the function will only be called once? In my test it's only called once, but I can't see any documentation stating I can rely on that always being the case.

Edit

I can guess how it is implemented, but c'mon: we're developers. We shouldn't be muddling through on guesses and assumptions. For example, will all future implementations be the same? Will another platform's implementation of the language be the same? That depends on the specifications of the language and what guarantees it offers. For example, a future or different platform implementation (not a good one, but it's possible) may do this in the ?? implementation:

return ReallyComplexFunction() == null ? 42 : ReallyComplexFunction();

That, would call the ReallyComplexFunction twice if it didn't return null. (although this looks a ridiculous implementation, if you replace the function with a nullable variable it looks quite reasonable: return a == null ? 42 : a)

As stated above, I know in my test it's only called once, but my question is does the C# Specification guarantee/specify that the left-hand side will only be called once? If so, where? I can't see any such mention in the C# Language Specification for ?? operator (where I originally looked for the answer to my query).

noelicus
  • 14,468
  • 3
  • 92
  • 111
  • 14
    why do you think it would be called twice? – Mitch Wheat Nov 12 '13 at 14:04
  • The ?? operator calls the left, sees if it's null, if it is then returns right. It should only be called once – DotNetRussell Nov 12 '13 at 14:05
  • Where is this question even coming from? You refer to "the function" but show two different ones, it's not even clear to which line you're even referring to. -1 for stupid question and vagueness. You couldn't be bothered to just *run* it and find out? – tnw Nov 12 '13 at 14:06
  • Your first line doesn't even make sense. Doubt that compiles. – tnw Nov 12 '13 at 14:08
  • In the future, you can find the answer to these types of questions in the [C# Language Specification](http://msdn.microsoft.com/en-us/library/ms228593(v=vs.90).aspx) – Jim Mischel Nov 12 '13 at 14:10
  • 3
    It's not SUCH a silly question. There are freaky cases where the left hand of ?? can be called twice, see here http://stackoverflow.com/q/6256847/2609288 – Baldrick Nov 12 '13 at 14:10
  • 1
    @Baldrick: The answer to that question determines the behaviour to be a bug in the compiler, i.e. it is not expected behaviour. – Mitch Wheat Nov 12 '13 at 14:22
  • @tnw Please read the question. I did test it/run it and I want to know if it's *guaranteed* as part of the language spec. I have padded out the psuedocode to real code since you apparently didn't understand it. – noelicus Nov 12 '13 at 15:23
  • 1
    @Baldrick, thanks. That's an interesting case you've cited. Also helps to cement the assumption that it should be called once! – noelicus Nov 12 '13 at 15:23
  • 2
    **That is not the specification**. Do a search for the C# specification, then read section 7.13, which clearly answers your question: "*At run-time, `a` is first evaluated. If `a` is not null, `a` becomes the result. Otherwise, `b` is evaluated and converted to type `A`, and this becomes the result.*" – Eric Lippert Nov 12 '13 at 15:49
  • @noelicus If you're going to include pseudocode, maybe you should indicate that it's pseudocode. You even say explicitly that it's code so I'm forced to assume you think `int? ReallyComplexFunction();` is valid code. – tnw Nov 12 '13 at 15:51
  • 1
    I thought the "..." inferred it was not entire code. I guess "pseudocode" is the wrong term really. "..." as in "fill in the blanks" ... I was trying to be concise! – noelicus Nov 12 '13 at 17:08
  • @EricLippert thank you. Google's first shot *is* the link I referred to (and the link in one of the answers). I now see it's the docx download I really want. Great stuff. – noelicus Nov 12 '13 at 17:12

7 Answers7

9

The ?? operator will evaluate the left side once, and the right side zero or once, depending on the result of the left side.

Your code

int i = ReallyCleverFunction() ?? 42;

Is equivalent to (and this is actually very close to what the compiler actually generates):

int? temp = ReallyCleverFunction();
int i = temp.HasValue ? temp.Value : 42;

Or more simply:

int i = ReallyCleverFunction().GetValueOrDefault(42);

Either way you look at it, ReallyCleverFunction is only called once.

p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
4

The ?? operator has nothing to do with the left hand. The left hand is run first and then the ?? operator evaluates its response.

In your code, ReallyCleverFunction will only run once.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
0

It will be only called once. If the value of ReallyCleverFunction is null, the value 42 is used, otherwise the returned value of ReallyCleverFunction is used.

Siim Nelis
  • 882
  • 7
  • 10
0

It will evaluate the function, then evaluate the left value (which is the result of the function) of the ?? operator. There is no reason it would call the function twice.

David S.
  • 5,965
  • 2
  • 40
  • 77
0

It is called once and following the documentation I believe this should be sufficient to assume it is only called once:

It returns the left-hand operand if the operand is not null; otherwise it returns the right operand.

?? operator

Ric
  • 12,855
  • 3
  • 30
  • 36
0

It will only be run once because the ?? operator is just a shortcut.

Your line

int i = ReallyCleverFunction() ?? 42;

is the same as

int? temp = ReallyCleverFunction();
int i;
if (temp != null)
{
    i = temp.Value;
} else {
    i = 42;
}

The compiler does the hard work.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
0

Firstly, the answer is yes it does guarantee it will only evaluate it once, by inference in section 7.13 of the official C# language specification.

Section 7.13 always treats a as an object, therefore it must only take the return of a function and use that in the processing. It says the following about the ?? operator (emphasis added):

• If b is a dynamic expression, the result type is dynamic. At run-time, a is first evaluated. If a is not null, a is converted to dynamic, and this becomes the result. Otherwise, b is evaluated, and this becomes the result.
• Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
• Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
• Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.

As a side-note the link given at the end of the question is not the C# language specification despite it's first ranking in a Google Search for the "C# language specification".

noelicus
  • 14,468
  • 3
  • 92
  • 111