Почему &&
предпочтительнее&
и ||
предпочтительнее |
?
Я спросил кого-то, кто программировал годами, и он объяснил:
Например, in if (bool1 && bool2 && bool3) { /*DoSomething*/ }
, bool1
должно быть истинным, чтобы он мог проверить, bool2
который должен быть истинным, прежде чем перейти к bool3
и т. Д. Если бы я использовал один&
вместо этого нет никакого порядка для теста, даже если все они должны быть истинными для перейти к следующей строке, так почему это все равно имеет значение?
Примечание: я хотел бы отметить, что я программный эквивалент малыша, и это не серьезный или срочный вопрос. Это больше вопрос понимания, почему все должно быть сделано определенным образом, а не другим.
x & y
иx && y
всегда будут давать одинаковый результат, если x и y являются выражениями логического типа. На самом деле единственное различие в этом случае заключается в томx & y
, что y всегда вычисляется.Ответы:
В большинстве случаев,
&&
и||
предпочтительнее&
и|
потому, что первые имеют короткое замыкание, что означает, что оценка отменяется, как только результат становится ясным.Пример:
Если
CanExecute
возвращаетсяfalse
, полное выражение будетfalse
, независимо от возвращаемого значенияCanSave
. Из-за этогоCanSave
не выполняется.Это очень удобно при следующих обстоятельствах:
TryGetValue
возвращает,false
если указанный ключ не найден в словаре. Из-за короткого замыкания&&
,value.Contains("test")
выполняется только, когдаTryGetValue
возвращаетсяtrue
и, следовательноvalue
, нетnull
. Если бы вместо этого вы использовали побитовый оператор AND&
, вы бы получилиNullReferenceException
если ключ не найден в словаре, потому что вторая часть выражения выполняется в любом случае.Аналогичным, но более простым примером этого является следующий код (как упомянуто TJHeuvel):
CanExecute
выполняется только еслиop
нетnull
. Еслиop
естьnull
, первая часть выражения (op != null
) оценивается,false
а оценка остальных (op.CanExecute()
) пропускается.Помимо этого, технически, они тоже разные:
&&
и||
могут быть использованы толькоbool
тогда&
и|
может быть использован на любой интегрального типа (bool
,int
,long
,sbyte
, ...), потому что они являются битовые операторы.&
является побитовым оператором И и|
является побитовым оператором ИЛИ .Точнее говоря, в C # эти операторы (
&
,|
[и^
]) называются «логическими операторами» (см. Спецификацию C # , глава 7.11). Существует несколько реализаций этих операторов:int
,uint
,long
иulong
, глава 7.11.1):Они реализуются , чтобы вычислить результат побитового операндов и оператора, то есть
&
это реализовать , чтобы вычислить побитовое логическое иAND
т.д.они реализованы для выполнения логической операции базового типа перечисления.
результат не вычисляется с использованием побитовых вычислений. Результат в основном ищется на основе значений двух операндов, потому что количество возможностей очень мало.
Поскольку оба значения используются для поиска, эта реализация не имеет короткого замыкания.
источник
if(op != null && op.CanExecute())
. Поскольку вторая причина не оценивается, когда первая не истинна, это допустимо.TryGetValue
примере. Но да, это еще один хороший пример этого.&
или|
используется с не булевыми аргументами (то есть, что делают операторы) для блага всех новичков.Чтобы объяснить очень ясно, что это значит (хотя другие ответы намекают на это - но, вероятно, используйте терминологию, которую вы не понимаете).
Следующий код:
Действительно скомпилировано в это:
Где следующий код скомпилирован именно так, как он представлен:
Это называется коротким замыканием. В общем, вы всегда должны использовать
&&
и||
в ваших условиях.Бонусные метки: есть один сценарий, когда ты не должен. Если вы находитесь в ситуации, когда производительность имеет решающее значение (а это решающее значение наносекунды ), используйте короткое замыкание только тогда, когда вам необходимо (например,
null
проверка) - так как короткое замыкание является переходом / скачком; что может привести к неправильному прогнозированию ветвлений на вашем процессоре;&
гораздо дешевле&&
. Существует также сценарий, когда короткое замыкание может фактически нарушить логику - взгляните на мой ответ .Diatribe / Monologue : Относительно неправильного предсказания ветви, которое большинство блаженно игнорируют. Цитируя Энди Ферта (который работает над играми в течение 13 лет): «Это может быть более низкий уровень, когда люди думают, что им нужно идти ... но они ошибаются. Понимание того, как аппаратное обеспечение, которое вы программируете, относится к веткам, может влияет на производительность в огромной степени ... гораздо больше, чем большинство программистов могут оценить re: death на тысячу сокращений ".
Вот эталон для неверующих. Лучше всего запустить процесс в RealTime / High, чтобы смягчить эффект планировщика: https://gist.github.com/1200737
источник
(x && y)
переводит туда,LOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;
где(x & y)
переводитсяLOAD x; LOAD y; AND; BRANCH_FALSE;
. Одна ветка против двух.Логический оператор (
||
и&&
) против побитового оператора (|
и&
).Наиболее существенное различие между логическим оператором и побитовым оператором заключается в том, что логический оператор принимает два логических значения и выдает логическое значение, в то время как побитовый оператор принимает два целых числа и выдает целое число (примечание: целые числа означают любой целочисленный тип данных, а не только int).
Чтобы быть педантичным, побитовый оператор берет битовую комбинацию (например, 01101011) и выполняет побитовое И / ИЛИ для каждого бита. Так, например, если у вас есть два 8-битных целых числа:
в то время как логический оператор работает только в
bool
:Во-вторых, часто можно использовать побитовый оператор в bool, поскольку true и false эквивалентны 1 и 0 соответственно, и бывает, что если вы переводите true в 1 и false в 0, то выполняете битовую операцию, а затем преобразуете ненулевое значение на истину и ноль на ложь; бывает, что результат будет таким же, если вы только что использовали логический оператор (проверьте это для упражнения).
Другое важное отличие состоит также в том, что логический оператор закорочен . Таким образом, в некоторых кругах [1] вы часто видите людей, делающих что-то вроде этого:
что означает: «если человек существует (то есть не является нулевым), попытайтесь ударить его / ее, и если удар удастся (то есть вернет истину), тогда сделайте танец победы» .
Если бы вы использовали вместо этого побитовый оператор, это:
будет переводиться как: «если человек существует (то есть не является нулевым), и удар успешен (то есть возвращает истину), тогда сделайте танец победы» .
Обратите внимание, что в короткозамкнутом логическом операторе
person.punch()
код может вообще не выполняться, если онperson
равен нулю. Фактически, в этом конкретном случае второй код выдаст нулевую ссылку, если онperson
равен нулю, так как он пытается вызватьperson.punch()
независимо от того, является ли пользователь нулевым или нет. Такое поведение не оценки правильного операнда называется коротким замыканием .[1] Некоторые программисты будут упрекать за то, что они помещают вызов функции, который имеет побочный эффект внутри
if
выражения, в то время как для других это распространенная и очень полезная идиома.Поскольку побитовый оператор работает одновременно с 32-разрядными системами (если вы работаете на 32-разрядных компьютерах), он может привести к более элегантному и быстрому коду, если вам нужно сравнить огромное количество условий, например
Чтобы сделать то же самое с логическими операторами, потребуется неловкое количество сравнений:
Классический пример, в котором используются битовые шаблоны и побитовый оператор, - в разрешениях файловой системы Unix / Linux.
источник
В случае:
будет работать как ожидалось.
Но:
потенциально может выдать исключение нулевой ссылки.
источник
Коротко и просто:
1 && 2
= true,потому что
1 = true (не ноль) в C
2 = true (не ноль) в C
true
ANDS логически,true
чтобы датьtrue
.Но
1 & 2
= 0 = ложь,потому что
1 = 0001 в двоичном формате
2 = 0010 в двоичном виде
0001 И поразрядно с 0010, чтобы дать 0000 = 0 в десятичном виде.
Аналогично для || и | операторы тоже ...!
источник
1 && 2
это незаконно в C #&&
версия короткого замыкания&
.Если мы оцениваем
false & true
, мы уже знаем по первому аргументу, что результат будет ложным.&&
Версия оператора будет возвращать результат , как только он может, а не оценивать целое выражение. Существует также аналогичная версия|
оператора||
.источник
безопасно
произойдет сбой, если список не имеет нужного размера.
источник
Операторы C # должны объяснить, почему:
По сути, наличие двух
&
или несколько|
означает, что это условный, а не логический, так что вы можете увидеть разницу между двумя.& Оператор имеет пример использования одного
&
.источник
Хорошо, по номиналу
дать тот же ответ. Однако, как вы показали, если у вас есть более сложный вопрос, то:
Если
a
это не так, и, возможноb
, это функция, где она должна отключиться, подключиться к чему-то, получить это, сделать это, принять решение ... зачем? Пустая трата времени, вы знаете, что это уже не удалось. Зачем заставлять машину выключаться и делать лишнюю бессмысленную работу?Я всегда использовал,
&&
потому что сначала я ставлю наиболее вероятный сбой, а значит, меньше вычислений, прежде чем идти дальше, когда нет смысла. Если нет способа предсказать менее вероятный выбор, например, у вас есть логическое значение для ограничения вывода данных, что-то вроде:Если это не так
limit
, не пытайтесь проверить ключ, который может занять больше времени ..источник
При использовании в логическом выражении, например, в операторе if,
&&
предпочтительнее, поскольку он прекращает вычислять выражения, как только встречается первый ложный результат. Это возможно, потому что ложное значение приведет к тому, что все выражение будет ложным. Аналогично (и снова в логических выражениях)||
предпочтительнее, потому что он прекратит вычислять выражения, как только встретит истинное выражение, потому что любое истинное значение приведет к тому, что все выражение будет истинным.Если, однако, выражения или-или-и-ed вместе имеют побочные эффекты, и вы хотите, чтобы все это происходило в результате вашего выражения (независимо от результата логического выражения), тогда
&
и|
можно использовать. С другой стороны ,&&
и||
операторы могут быть полезны в качестве защищает от нежелательных побочных эффектов (таких как указатель нулевого вызывая исключение быть выброшены).Операторы
&
and|
также могут использоваться с целыми числами, и в этом случае они дают целочисленный результат, который представляет собой два операнда и-ed или or-ed вместе на уровне битов. Это может быть полезно, когда двоичные биты целочисленного значения используются в качестве массива значений true и false. Чтобы проверить, включен или выключен определенный бит, битовая маска битовая добавляется со значением. Чтобы включить немного, одну и ту же маску можно поразрядно добавить к значению. Наконец, чтобы отключить немного, побитовое дополнение (использование~
) маски побитово и отредактировано со значением.В языках, отличных от C #, следует соблюдать осторожность при использовании логических и побитовых режимов & и |. В приведенном выше коде
if
условное выражение оператора(a & 4) != 0
является безопасным способом выражения этого условия, но во многих языках, подобных С, условные операторы могут просто обрабатывать нулевые целые значения как ложные, а ненулевые целые значения - как истинные. (Причина этого связана с доступными инструкциями процессора условных переходов и их отношением к нулевому флагу, который обновляется после каждой целочисленной операции.) Таким образомìf
, проверка оператора на ноль может быть удалена, а условие может быть сокращено до(a & 4)
.Это может вызвать путаницу и, возможно, даже проблемы, когда выражения объединяются с использованием битовых и операторных возвращаемых значений, у которых нет битов, которые выстраиваются в линию. Рассмотрим следующий пример, где желательны побочные эффекты двух функций, прежде чем проверять, что они обе были успешными (как они определяют, возвращая ненулевое значение):
В C, если
foo()
возвращает 1 иbar()
возвращает 2, «что-то» не будет сделано, потому что1 & 2
это ноль.C # требует условных операторов, таких как
if
наличие логического oeprand, а язык не позволяет приводить целочисленное значение к логическому значению. Таким образом, приведенный выше код будет генерировать ошибки компилятора. Правильнее было бы выразиться следующим образом:источник
Если вы программист на старом таймере, будьте осторожны . C # действительно удивил меня.
MSDN говорит для
|
оператора:(Акцент мой.) Булевы типы обрабатываются специально, и в этом контексте вопрос только начинает обретать смысл, и разница, как и другие, уже раскрыта в их ответах:
и то, что является предпочтительным, зависит от многих вещей, таких как побочные эффекты, производительность и удобочитаемость кода, но обычно операторы короткого замыкания предпочтительны также потому, что их лучше понимают люди с таким же опытом, как я.
Причина в том, что я могу рассуждать так: поскольку в C нет реального логического типа, вы можете использовать побитовый оператор,
|
и его результат оценивается как истинный или ложный в условии if. Но это неправильное отношение к C #, потому что для булевых типов уже есть особый случай.источник
Это важно, потому что, если стоимость оценки bool2 (например) высока, а bool1 ложна, вы сэкономили немало вычислений, используя && over &
источник
Потому
&&
и||
используются для управления потоком, как иif/else
есть. Это не всегда об условностях. Вполне разумно написать как утверждение, а не какif
илиwhile
условно, следующее:или даже
Дело не только в том, что их легче набирать, чем эквивалентные
if/else
версии; они также намного легче читать и понимать.источник
&& и & означают две совершенно разные вещи и дают вам два разных ответа.
1 && 2
доходность 1 («истина»)1 & 2
доходность 0 («ложь»)&&
является логическим оператором - это означает, что «истина, если оба операнда истинны»&
- это побитовое сравнение. Это означает «скажите мне, какие биты установлены в обоих операндах»источник
1 && 2
выдает ошибку компилятора: «Ошибка 4 Оператор« && »не может быть применена к операндам типа« int »и« int »»Самый быстрый (и слегка тупой) способ объяснить это людям, которым НЕ НУЖНО знать точные операции кода при этом,
&& выполняет проверку каждого из этих условий, пока не обнаружит ложное и не вернет весь результат как ложное
|| выполняет проверку каждого из этих условий, пока не найдет истину и не вернет весь результат как истину.
& выполняет условия на основе MATHS ОБА / ВСЕХ условий и имеет дело с результатом.
| выполняет на основе MATHS апо ОБА / ВСЕ условия и имеет дело с результатом.
Я никогда не сталкивался с тем, что мне нужно было использовать & или |в утверждении if. Я в основном использую его для вырезания шестнадцатеричных значений в цвета его компонентов с помощью побитового сдвига.
НАПРИМЕР:
В рамках этой операции "& 0xFF" заставляет смотреть только двоичное значение. Я лично не нашел применение для | все же хотя.
источник
Просто,
if exp1 && exp2
если exp1
flase
не проверять exp2но
if exp1 & exp2
если exp1 равен
false
ortrue
проверить exp2и редко люди используют,
&
потому что они редко хотят проверить exp2, если exp1false
источник