Ответ 1
Ну, если "кэшированием" вы хотите сохранить его во временной переменной, тогда да.
Эта конструкция:
var result = (getResult() ?? new SomeClass());
можно считать эквивалентным этому:
var <temp> = getResult();
if (<temp> == null)
<temp> = new SomeClass();
result = <temp>;
Это также говорит о том, что вторая часть, операнд после ??
вообще не выполняется, если первый операнд не является null
.
Итак, чтобы ответить на ваши конкретные вопросы:
- Каждый операнд оценивается не более одного раза
- Второй операнд оценивается только в том случае, если первый оценивает значение
null
Заметьте также, что вы можете связать их:
var result = first() ?? second() ?? third() ?? fourth();
Результат:
- Вычисляет
first()
- Если
first()
оценивается какnull
, оцениваетсяsecond()
- Если
second()
оценивается какnull
, то оцениваетthird()
- Если все вышеперечисленное оценивается как
null
, в итоге оцениваетсяfourth
В результате получается первое (не предназначенное для каламбур) ненулевое значение.
Этот тип кода скоро станет еще лучше в новом С# с новым оператором ?.
:
var result = first?.second?.third;
Это базовая обработка .
, т.е. он будет читать член second
first
, а затем член third
любого second
, но он остановится при первом null
, а также обязательно будет оценивать каждый шаг только один раз:
(obj as IDisposable)?.Dispose();
obj as IDisposable
будет оцениваться только один раз.
TryGetObjectToSave()?.Save();
Вызов только TryGetObjectToSave()
один раз, и если он что-то вернет, метод Save()
для этого будет вызван.