Подтвердить что ты не робот

Какова наилучшая практика в отношении оценки короткого замыкания на С#?

Ответ и последующая дискуссия в комментариях в другом потоке побудили меня спросить:

В С# || и && являются короткозамкнутыми версиями логических операторов | и соответственно.

Пример использования:

if (String.IsNullOrEmpty(text1) | String.IsNullOrEmpty(text2) | String.IsNullOrEmpty(text3))
{
    //...
}

против

if (String.IsNullOrEmpty(text1) || String.IsNullOrEmpty(text2) || String.IsNullOrEmpty(text3))
{
    //...
}

Что касается практики кодирования, которая лучше использовать и почему?

Примечание. Я понимаю, что этот вопрос похож на на этот вопрос, но я считаю, что он требует обсуждения на конкретном языке.

4b9b3361

Ответ 1

Что касается практики кодирования, которая лучше использовать и почему?

Простой ответ: всегда используйте короткозамкнутые версии. Тебе просто нечего делать. Кроме того, вы делаете код более понятным, потому что вы выражаете свое намерение: логическая оценка. Использование побитовых (логических) операций подразумевает, что вы хотите именно это: битовые операции, а не логическую оценку (даже если MSDN называет их "логическими операторами", когда применяется к логическим значениям).

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

bool nullorempty = str == null || str.Length == 0;

(Обратите внимание, что для решения этой конкретной проблемы уже существует более эффективная функция, а именно string.IsNullOrEmpty, которую вы также использовали в своем вопросе.) Этот код невозможен с побитовыми логическими операциями, потому что даже если str были null, второе выражение будет оценено, в результате получится NullReferenceException.

EDIT. Если вы хотите, чтобы побочные эффекты возникали в логическом контексте, пожалуйста, не используйте побитовые операции. Это типичный пример слишком умного. Следующий сопровождающий код (или даже сам, через несколько недель) увидит, что этот код будет думать "хм, этот код можно очистить, чтобы использовать условные операторы", таким образом, случайно нарушив код. Жаль, кто отвечает за исправление этой ошибки.

Вместо этого, если вам приходится полагаться на сторону, эффекты, сделать их явными:

bool hasBuzzed = checkMakeBuzz();
bool isFrobbed = checkMakeFrob();
bool result = hasBuzzed || isFrobbed;

Предоставлено три строки вместо одной. Но в результате получается гораздо более четкий код.

Ответ 2

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

Я иногда использую логические сравнения, когда у меня есть серия (недорогих) условных выражений, которые должны быть выполнены. Например:

bool isPasswordValid = true;

isPasswordValid &= isEightCharacters(password);
isPasswordValid &= containsNumeric(password);
isPasswordValid &= containsBothUppercaseAndLowercase(password);

return isPasswordValid;

По-моему, вышеизложенное более читаемо, чем:

return (isEightCharacters(password) &&
        containsNumberic(password)  &&
        containsBothUppercaseAndLowercase(password));

Недостатком является то, что он немного более эзотерический.

Ответ 3

Используйте && и ||, когда вы только заботитесь о результатах и ​​хотите узнать этот результат как можно скорее, и ни одно из ваших выражений не имеет побочных эффектов, которые должны произойти, даже если булевское условие не выполняется. То есть, почти всегда.

Используйте & и |, когда каждое выражение должно быть оценено (например, если у вас есть побочные эффекты от ваших выражений). Но поскольку у вас никогда не должно быть побочных эффектов, от которых зависит ваша программа, даже если логическое условие не выполняется, вероятно, вы не должны использовать & и |.

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

if (false & somethingThatUpdatesTheDatabase()) { /* ... */ }