Допустим, вы использовали язык C-стиля без &&
и нуждались в создании эквивалентного кода, как в вашем вопросе.
Ваш код будет:
if(smartphone != null)
{
if(smartphone.GetSignal() > 50)
{
// Do stuff
}
}
Эта модель будет много.
Теперь представьте, что версия 2.0 нашего гипотетического языка вводит &&
. Подумай, как круто это было бы!
&&
это признанный, идиоматический способ делать то, что делает мой пример выше. Использовать его - не плохая практика, на самом деле это плохая практика - не использовать его в случаях, подобных описанному выше: опытному программисту на таком языке было бы интересно узнать, где else
была или другая причина, по которой он не поступал обычным образом.
Язык является умным, потому что он знает, что если первый оператор, если ложь, то нет смысла даже оценивать второй оператор, и поэтому исключение нулевой ссылки никогда не выдается.
Нет, вы умны, потому что вы знали, что если первое утверждение было ложным, то нет смысла даже оценивать второе утверждение. Язык туп, как скала, и сделал то, что вы сказали, чтобы сделать. (Джон Маккарти был еще умнее и понял, что оценка короткого замыкания будет полезна для языков).
Разница между умным и умным языком очень важна, потому что хорошие и плохие практики часто сводятся к тому, что вы настолько умны, насколько это необходимо, но не более умны.
Рассмотреть возможность:
if(smartphone != null && smartphone.GetSignal() > ((range = (range != null ? range : GetRange()) != null && range.Valid ? range.MinSignal : 50)
Это расширяет ваш код для проверки range
. Если значение range
равно NULL, оно пытается установить его с помощью вызова, GetRange()
хотя это может привести к сбою, поэтому range
все равно может быть NULL. Если диапазон не равен нулю после этого, и Valid
тогда используется его MinSignal
свойство, в противном случае используется значение по умолчанию 50
.
Это &&
тоже зависит от того , но поместить это в одну строку, вероятно, слишком умно (я не уверен на 100%, что я правильно понял, и я не собираюсь перепроверять, потому что этот факт демонстрирует мою точку зрения).
Дело не в &&
том, что проблема здесь, но способность использовать это, чтобы поместить много в одно выражение (хорошая вещь), увеличивает нашу способность писать трудные для понимания выражения без необходимости (плохая вещь).
Также:
if(smartphone != null && (smartphone.GetSignal() == 2 || smartphone.GetSignal() == 5 || smartphone.GetSignal() == 8 || smartPhone.GetSignal() == 34))
{
// do something
}
Здесь я совмещаю использование &&
с проверкой на определенные значения. В случае телефонных сигналов это нереально, но в других случаях возникает. Вот пример того, что я недостаточно умен. Если бы я сделал следующее:
if(smartphone != null)
{
switch (smartphone.GetSignal())
{
case 2: case 5: case 8: case 34:
// Do something
break;
}
}
Я бы выиграл как в удобочитаемости, так и в производительности (скорее всего, несколько вызовов GetSignal()
не были бы оптимизированы).
Здесь опять проблема не столько &&
в том, чтобы взять этот конкретный молоток и увидеть все остальное как гвоздь; не используя его, позвольте мне сделать что-то лучше, чем использовать его.
Последний случай, который отходит от лучших практик:
if(a && b)
{
//do something
}
По сравнению с:
if(a & b)
{
//do something
}
Классический аргумент относительно того, почему мы могли бы отдать предпочтение последнему, заключается в том, что при оценке того, b
что мы хотим, a
есть ли какой-то побочный эффект , является ли это правдой или нет. Я не согласен с этим: если этот побочный эффект так важен, сделайте так, чтобы это происходило в отдельной строке кода.
Тем не менее, с точки зрения эффективности любой из двух, вероятно, будет лучше. Первый, очевидно, будет выполнять меньше кода (не оценивая его b
по одному пути кода), что может сэкономить нам любое количество времени, необходимое для оценки b
.
Первый, хотя и имеет еще одну ветку. Подумайте, перепишем ли мы это на нашем гипотетическом языке C-стиля без &&
:
if(a)
{
if(b)
{
// Do something
}
}
Это дополнительное if
скрыто в нашем использовании &&
, но оно все еще там. И как таковой, это тот случай, когда происходит предсказание ветвления и, следовательно, потенциально неправильное предсказание ветвления.
По этой причине if(a & b)
код может быть более эффективным в некоторых случаях.
Здесь я бы сказал, что if(a && b)
по-прежнему это лучший практический подход для начала: более распространенный, единственный жизнеспособный в некоторых случаях (где b
будет ошибка, если a
ложь) и более быстрый, чем нет. Стоит отметить, что if(a & b)
в некоторых случаях это часто полезная оптимизация.