2013-11-12 7 views
1

Например, если этот код:Есть ли? оператор гарантирует только однократное выполнение левого аргумента?

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

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

... это гарантирует, что функция будет вызываться только один раз? В моем тесте он называется только один раз, но я не вижу никакой документации, в которой я могу полагаться, что это всегда так.

Редактировать

я могу догадаться, как это реализовано, но c'mon: мы разработчики. Мы не должны путаться с догадками и предположениями. Например, будут ли все будущие реализации одинаковыми? Будет ли реализация другой платформы языком одинаковой? Это зависит от спецификаций и гарантирует. Например, будущее или другой платформы (не хороший, но это возможно), может сделать это в ?? реализации:

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

То, назвали бы ReallyComplexFunction дважды, если он не вернется null. (Хотя это выглядит нелепой реализации, если заменить функцию с обнуляемого переменной выглядит вполне разумно: return a == null ? 42 : a)

Как уже говорилось выше, я знаю, в моем тесте это только раз, но мой вопрос делает C# Спецификация гарантирует/указывает, что левая сторона будет вызываться только один раз? Если да, то где? Я не вижу такого упоминания в C# Language Specification for ?? operator (где я первоначально искал ответ на мой запрос).

+14

Почему вы думаете, что это будет называться дважды? –

+0

The ?? оператор вызывает левый, видит, является ли он нулевым, если он затем возвращается вправо. Его следует называть только один раз –

+0

Где этот вопрос, даже исходящий? Вы ссылаетесь на «функцию», но показываете два разных, даже не понятно, к какой строке вы даже обращаетесь. -1 для глупого вопроса и неопределенности. Вы не могли бы беспокоиться, чтобы просто * запустить * его и узнать? – tnw

ответ

0

Во-первых, ответ да, он гарантирует, что он будет оценивать его только один раз, путем вывода в разделе 7.13 из the official C# language specification.

Раздел 7.13 всегда рассматривает объект a как объект, поэтому он должен принимать только возврат функции и использовать ее при обработке. В нем говорится следующее о оператор (выделено мной):

• Если b является динамическим выражением, тип результата является динамическим. Во время выполнения сначала оценивается а. Если a не является нулевым, a преобразуется в динамическое, и это становится результатом. В противном случае b оценивается, и это становится результатом.
• В противном случае, если существует A и является типом NULL, и существует неявное преобразование от b до A0, результатом является A0. Во время выполнения сначала оценивается а. Если a не является нулевым, a разворачивается для ввода A0, и это становится результатом. В противном случае b оценивается и преобразуется в тип A0, и это становится результатом.
• В противном случае, если существует A и существует неявное преобразование от b до A, то результатом будет A. В момент выполнения сначала оценивается a. Если a не является нулевым, a становится результатом. В противном случае b оценивается и преобразуется в тип A, и это становится результатом.
• В противном случае, если b имеет тип B и существует неявное преобразование от a до B, тип результата - B. Во время выполнения сначала оценивается a. Если a не является нулевым, a разворачивается для ввода A0 (если существует A и имеет значение NULL) и преобразуется в тип B, и это становится результатом. В противном случае b оценивается и становится результатом.

Как побочный отметить связь, приведенную в конце вопроса не C# языка спецификаций несмотря на это первый рейтинг в Google Search для «языковой спецификации C#».

4

Оператор ?? не имеет никакого отношения к левой руке. Левую руку запускают сначала, а затем оператор ?? оценивает свой ответ.

В вашем коде ReallyCleverFunction будет работать только один раз.

9

Оператор ?? будет оценивать левую сторону один раз, а правую сторону - ноль или один раз, в зависимости от результата левой стороны.

Ваш код

int i = ReallyCleverFunction() ?? 42; 

эквивалентно (и это на самом деле очень близко к тому, что на самом деле генерирует компилятор):

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

Или еще проще:

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

Либо как вы смотрите на него, ReallyCleverFunction называется только один раз.

+4

+1 для выключения вероятного сгенерированного ИЛ. –

0

Он будет вызываться только один раз. Если значение ReallyCleverFunction равно null, используется значение 42, в противном случае используется возвращаемое значение ReallyCleverFunction.

0

Он будет оценивать функцию, а затем оценивать левое значение (которое является результатом функции) оператора ??. Нет причин, по которым он будет вызывать функцию дважды.

0

Он вызывается один раз и после документации я считаю, что это должно быть достаточно, чтобы предположить, что это только раз:

возвращает левый операнд, если операнд не является нулевым; в противном случае возвращает правый операнд.

?? operator

0

Он будет работать только один раз, потому что оператор ?? просто ярлык.

Ваша линия

int i = ReallyCleverFunction() ?? 42; 

такая же, как

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

компилятор делает тяжелую работу.

Смежные вопросы