Скажімо, ви використовували мову в стилі С без &&
і потрібно було робити еквівалентний код, як у вашому запитанні.
Ваш код буде:
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
.
Перша, хоча також має ще одну галузь. Поміркуйте, чи перепишемо ми його на гіпотетичній мові С-стилю без &&
:
if(a)
{
if(b)
{
// Do something
}
}
Ця зайва if
прихована у нашому використанні &&
, але вона все ще є. І як такий - це випадок, коли відбувається передбачення гілок, і, можливо, тому неправильне прогнозування галузі.
З цієї причини if(a & b)
код може бути більш ефективним у деяких випадках.
Тут я б сказав, що if(a && b)
це все-таки найкращий підхід для початку: Поширеніший, єдиний життєздатний в деяких випадках (де b
помилка, якщо a
помилковий), і швидше частіше, ніж ні. Варто відзначити, що if(a & b)
часто корисна оптимізація щодо неї в деяких випадках.