Well, if by "caching" you mean storing it in a temporary variable, then yes.
This construct:
var result = (getResult() ?? new SomeClass());
can be thought of to be equivalent to this:
var <temp> = getResult();
if (<temp> == null)
<temp> = new SomeClass();
result = <temp>;
This also tells you that the second part, the operand after ?? isn't executed at all if the first operand is not null.
So to answer your concrete questions:
- Each operand is evaluated at most once
- The second operand is only evaluated if the first one evaluates to
null
Note also that you can chain these:
var result = first() ?? second() ?? third() ?? fourth();
Which results in:
- Evaluates
first()
- If
first() evaluated to null, evaluates second()
- If
second() evaluated to null as well, evaluates third()
- If all of the above evaluated to
null, finally evaluates fourth
The result is the first (no pun intended) non-null value returned.
This type of code is about to get even better in new C# with the new ?. operator:
var result = first?.second?.third;
This is basic . handling, ie. it will read the second member of first, and then the third member of whatever second is, but it will stop at the first null, and will also make sure to evaluate each step only once:
(obj as IDisposable)?.Dispose();
obj as IDisposable will only evaluate once.
TryGetObjectToSave()?.Save();
Will only call TryGetObjectToSave() once, and if it returns something, the Save() method on that something will be called.