Оценка выражения слева направо
В C# гарантируется, что выражения вычисляются слева направо?
Например:
myClass = GetClass();
if (myClass == null || myClass.Property > 0)
continue;
Есть ли языки, которые не соответствуют?
9 ответов
Вы на самом деле ссылаетесь на языковую функцию, называемую "короткое замыкание логических выражений":
Это означает следующее: когда результат логического выражения больше не может измениться, например, когда становится ясно, что выражение будет оцениваться как "истина" или "ложь", несмотря ни на что, остальные части выражения не будут оцениваться.
Например, C#, Java или JavaScript делают это, и вы можете положиться на это на этих языках (чтобы ответить на ваш вопрос).
В вашем случае, если MyClass не равен NULL:
MyClass == null
оценивается как ложный- так как это выражение "или", вторая часть все еще может изменить результат, поэтому он оценивается
myClass.Property > 0
определяет конечный результат
если MyClass равен нулю:
MyClass == null
оценивает как истинное- поскольку это выражение "или", не имеет значения, что следует
- больше не проводится оценка, конечный результат верен
Есть языки, которые не замыкают логические выражения. Классический VB является примером, здесь "myClass.Property > 0" будет оценен и выдаст ошибку, если MyClass будет нулевым (в VB он называется "Nothing").
Короткое замыкание описано в разделе 7.11 спецификации C# 3.0:
Операция х || у соответствует операции х | y, за исключением того, что y оценивается, только если x не соответствует действительности.
Так что да, ты в порядке.
Что касается других языков - я никогда не люблю говорить на всех языках. В VB.NET вы можете использовать OrElse и AndAlso, которые являются короткозамкнутыми, но не имеют значения Or и And.
Но будь осторожен:
если у вас есть что-то вроде
sprintf(buf, "%s %s", func1(&var), func2(&var));
с побочными эффектами на var он не определен (в C я не уверен, определен ли порядок оценки на других языках), в каком порядке выполняются func1() и func2() (зависит от того, в каком порядке (слева или правильно) аргументы помещаются в стек и оцениваются оттуда.
Я не уверен, вы действительно заинтересованы в порядке или в оценке короткого замыкания?
Я не уверен на 100%, но, насколько я знаю, порядок оценки всегда будет одинаковым в C# (и я предполагаю, что большинство, если не все языки.net). Оценка короткого замыкания работает, как объяснено в предыдущих ответах.
Однако в C# вы можете отказаться от короткого замыкания, используя простые операторы (& вместо &&). Обычно вы хотите короткого замыкания, но это может быть случай, когда вы хотите выполнить все оценки.
В Java и Haskell && и || короткое замыкание.
Интересно отметить: в Haskell это естественно происходит с языком (вы можете определить свои собственные операторы, которые делают это), в то время как в Java и C# он специфичен для этих двух операторов.
Порядок оценки зависит от оператора, в данном случае от логического или ( ||
) определяется как то, что обычно называется коротким замыканием, для создания конструкций, подобных этой.
Операторы и / или в таких языках, как Ada, Visual Basic и Pascal, не закорачиваются. Они предоставляют дополнительные операторы для разрешения этой функции, такие как "и затем" и "или еще" в Аде.
На самом деле короткое замыкание является частью, но вам также необходимо знать, гарантирует ли язык их оценку слева направо. Например, C (ANSI, ISO, C99) НЕ гарантирует оценку слева направо. В примере кода было бы возможно проверить значение свойства перед проверкой на NULL или сделать оба одновременно... большинство компиляторов не делают этого, но ничто не мешает ему сделать это и полностью соответствовать спецификации. Это даже говорит вам НЕ писать такой код из-за этого.