Предположим, что myObj имеет значение null. Безопасно ли это писать?
if(myObj != null && myObj.SomeString != null)
Я знаю, что некоторые языки не будут выполнять второе выражение, потому что && оценивается как false до выполнения второй части.
Предположим, что myObj имеет значение null. Безопасно ли это писать?
if(myObj != null && myObj.SomeString != null)
Я знаю, что некоторые языки не будут выполнять второе выражение, потому что && оценивается как false до выполнения второй части.
да. В C# &&
и ||
являются короткими замыканиями и, таким образом, оценивают правую часть только в том случае, если левая сторона еще не определяет результат. С другой стороны, операторы &
и |
не замыкаются и всегда оценивают обе стороны.
Спецификация говорит:
Операторы
&&
и||
называются условными логическими операторами. Их также называют «замыкающими» логическими операторами.
...
Операцияx && y
соответствует операцииx & y
, за исключением того, чтоy
вычисляется, только еслиx
равноtrue
...
Операцияx && y
оценивается как(bool)x ? (bool)y : false
. Другими словами,x
сначала оценивается и преобразуется в типbool
. Затем, еслиx
равноtrue
,y
оценивается и преобразуется в типbool
, и это становится результатом операции. В противном случае результатом операции будетfalse
.
(Спецификация языка C#, версия 4.0–7.12, условные логические операторы)
Одно интересное свойство &&
и ||
заключается в том, что они замыкаются накоротко, даже если оперируют не логическими значениями, а типами, в которых пользователь перегрузил операторы &
или |
вместе с операторами true
и false
.
Операция
x && y
оценивается какT.false((T)x) ? (T)x : T.&((T)x, y)
, гдеT.false((T)x)
— это вызовoperator false
, объявленного вT
, аT.&((T)x
, y) — это вызов выбранногоoperator &
. Кроме того, значение (T)x оценивается только один раз.Другими словами,
x
сначала оценивается и преобразуется в типT
, аoperator false
вызывается для результата, чтобы определить, является лиx
определенноfalse
.
Затем, еслиx
определенно являетсяfalse
, результатом операции является значение, ранее вычисленное дляx
преобразуется в типT
.
В противном случае вычисляетсяy
, и выбранный оператор&
вызывается для значения, ранее вычисленного дляx
, преобразованного в типT
, и значения, вычисленного дляy
, для получения результата операции.
(Спецификация языка C#, версия 4.0 — 7.12.2 Пользовательские условные логические операторы)
false
с левой стороны возвращает true
и вместо этого возвращает левую сторону, а в противном случае вызывает пользовательский оператор &
. Так что это имитирует короткое замыкание, которое есть у bool
. Типичным применением этого является расширенный bool
, который может иметь третье состояние. Например, вы можете реализовать что-то похожее на DBBol
или bool?
.
- person CodesInChaos; 27.01.2011
Да, C# использует логическое сокращение.
Обратите внимание, что хотя C# (и некоторые другие языки .NET) ведут себя таким образом, это свойство языка, а не среды CLR.
AndAlso
и OrElse
, не при использовании And
и Or
, что, вероятно, всегда используют 90% людей.
- person Adam Robinson; 27.01.2011
Я знаю, что опаздываю на вечеринку, но в C# 6.0 это тоже можно сделать:
if(myObj?.SomeString != null)
Что то же самое, что и выше.
Также см.: Что делает вопрос оператор отметки и точки ?. значит в C# 6.0?
Ваш код в безопасности - && и || оба короткозамкнуты. Вы можете использовать операторы без короткого замыкания & или |, которые оценивают оба конца, но я действительно не вижу этого в большом количестве производственного кода.
конечно, на С# это безопасно, если первый операнд ложный, то второй никогда не оценивается.
Это совершенно безопасно. C# — один из таких языков.
Да, C# и большинство языков вычисляют предложения if слева направо.
Кстати, VB6 вычислит все это и выдаст исключение, если оно равно нулю...
And
не закорачивает, но &
тоже нет. (Возможно, 2+3 потому, что вы путаете синтаксический анализ с чем-то, что происходит во время выполнения...)
- person ; 27.01.2011
пример
if(strString != null && strString.Length > 0)
Эта строка вызовет нулевое исключение, если будут выполнены обе стороны.
Интересное примечание. Приведенный выше пример немного быстрее, чем метод IsNullorEmpty.
В C# &&
и ||
замкнуты накоротко, что означает, что оценивается первое условие, а остальные игнорируются, если ответ определен.
В VB.NET AndAlso
и OrElse
также закорочены.
В javaScript &&
и ||
тоже закорочены.
Я упоминаю VB.NET, чтобы показать, что у уродливого рыжеволосого приемного ребенка .net тоже иногда есть интересные вещи.
Я упоминаю javaScript, потому что если вы занимаетесь веб-разработкой, вы, вероятно, также можете использовать javaScript.
a || b
эквивалентно a ? a : b
, а a && b
эквивалентно a ? b : a
, за исключением того, что вычисляется только один раз. Это более заметно в JavaScript, где могут использоваться операнды произвольного типа. Другие языки, такие как C, не следуют этому принципу — они принимают операнды небулевых типов, но всегда возвращают логическое значение.
- person Stewart; 11.02.2020