2013-10-09 1 views
0

Сегодня я столкнулся с некоторым кодом, который проверял ряд ошибок. Единственное логическое значение использовалось на всем протяжении, но вместо того, чтобы переназначать его каждый раз с помощью =, оно было переназначено с помощью &=, что привело к бит мудному ANDing предыдущего значения булева и нового значения. Код выглядел примерно так:Есть ли причина использовать & =, а не просто = на логическом?

bool result = FirstCheck(); 
Assert(result); 
result &= SecondCheck(); 
Assert(result); 
... 

Теперь мне любопытно, почему кто-то это сделает? Это логически эквивалентно только переназначение логического значения, как показано на возможные ветви ниже:

  1. FirstCheck терпит неудачу (возвращает ложь) и программа терпит неудачу на утверждают, и никогда не делает его SecondCheck
  2. FirstCheck проходит (возвращается true), и программа переходит к SecondCheck. Если SecondCheck возвращает true, тогда результат будет истинным, потому что true & true = true. Если SecondCheck возвращает false, результат будет false, потому что true & false = false.

Поскольку нет никакой логической разницы, есть ли какая-то другая причина, возможно, предпочтительнее &=? Или, скорее всего, это реликвия какого-то старого кода, который никогда не менялся?

EDIT: Чтобы уточнить, Assert всегда является активным кодом. Я фактически наткнулся на этот код, исследуя ошибку, потому что утверждение не срабатывало.

ответ

1

Я думаю, что в начале это было:

bool result = FirstCheck(); 
result &= SecondCheck(); 
Assert(result); 

поэтому код проверял, что оба результата был положительным , но затем кто-то добавил Assert() после firstCheck().

Или человек может быть с фона C++ и думал, что побитовые операторы быстрее логических.

+0

Существуют случаи, когда битовые операторы быстрее, чем логических? – GBleaney

+0

Это * не * выполняет побитовое И. Оператор '&', вызываемый в буле в C#, просто выполняет короткое замыкание AND. Так что это никогда не будет быстрее, это может быть медленнее. Это нужно делать только в том случае, если важно, чтобы побочные эффекты «SecondCheck» выполнялись независимо от значения «результата». Либо это, либо это просто ошибка. – Servy

1

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

Предполагая, что result используется позже (за пределами утверждения), тогда есть разница, когда FirstCheck() возвращает false.

0

Как и другие, Assert может не всегда быть активным кодом. Предположим, что первая и третья проверка возвращают true, а вторая - возвращает false. Таким образом, если у вас было

x = FirstCheck() 
x = SecondCheck() 
x = ThirdCheck() 

тогда х равнялось бы true.

Но, если вы сделали

x &= FirstCheck() 
x &= SecondCheck() 
x &= ThirdCheck() 

х будет равен ложно

2

Да, причина в том, что вы используете один bool для накопления кодов возврата для нескольких функций.

Без & = вы переписываете код возврата с помощью последней функции для каждого вызова, поэтому вы всегда проверяете, была ли последняя функция успешной. С & = если одна функция возвращает false, тогда код возврата остается ложным с этой точки, поэтому вы знаете, что по крайней мере одна функция не удалась.

Это экономит написания кода, как этот

bFirstCheck == fn1(); 
bSecondCheck == fn2(); 
bThirdCheck == fn3(); 

if (bFirstCheck && bSecondCheck && bThirdCheck) { 
} 

Когда вы можете написать код:

bCheck = fn1(); 
bCheck &= fn2(); 
bCheck &= fn3(); 

if (true == bCheck) { 
} 
+2

Нет никакой причины сравнивать логическое значение с 'true'. Это нок. Просто напишите 'if (bCheck)'. – Servy

+0

Спасибо за большой ответ, однако, это не отвечает на мой конкретный вопрос, потому что Asserts между присваиваниями отрицает любые преимущества, упомянутые в вашем примере. – GBleaney

+0

Assert() применяется только к отладочным сборкам и используется здесь как чтобы предупредить вас о том, какая функция не удалась, она скомпилируется до NO-OP в сборках релизов. –

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