Должен ли я использовать `!IsGood` или`IsGood == false`?
Я продолжаю видеть код, который делает проверки, как это
if (IsGood == false)
{
DoSomething();
}
или это
if (IsGood == true)
{
DoSomething();
}
Я ненавижу этот синтаксис и всегда использую следующий синтаксис.
if (IsGood)
{
DoSomething();
}
или же
if (!IsGood)
{
DoSomething();
}
Есть ли причина использовать== true
' или же '== false
"?
Это удобочитаемость? Люди просто не понимают булевых переменных?
Кроме того, есть ли разница в производительности между этими двумя?
41 ответ
Я придерживаюсь того же синтаксиса, что и вы, он менее многословен.
Люди (больше начинающих) предпочитают использовать == true
просто чтобы быть уверенным, что это то, что они хотят. Они привыкли использовать оператор в своих условных выражениях... они нашли его более читабельным. Но как только вы стали более продвинутым, вы почувствовали раздражение, потому что это слишком многословно.
Я всегда хихикаю (или бросаю что-то в кого-то, в зависимости от моего настроения), когда сталкиваюсь
if (someBoolean == true) { /* ... */ }
потому что, конечно, если вы не можете полагаться на тот факт, что ваше сравнение возвращает логическое значение, то вы также не можете полагаться на сравнение результата с истинным, поэтому код должен стать
if ((someBoolean == true) == true) { /* ... */ }
но, конечно, это действительно должно быть
if (((someBoolean == true) == true) == true) { /* ... */ }
но конечно...
(Ах, сборка не удалась. Вернуться к работе.)
Я бы предпочел более короткий вариант. Но иногда == false
помогает сделать ваш код еще короче:
Для реальных сценариев в проектах, использующих C# 2.0, я вижу только одну хорошую причину сделать это: bool?
тип. Три состояния bool?
полезен, и таким образом легко проверить одно из его возможных значений.
На самом деле вы не можете использовать (!IsGood)
если IsGood
является bool?
, Но писать (IsGood.HasValue && IsGood.Value)
хуже чем (IsGood == true)
,
Поиграйте с этим примером, чтобы получить представление:
bool? value = true; // try false and null too
if (value == true)
{
Console.WriteLine("value is true");
}
else if (value == false)
{
Console.WriteLine("value is false");
}
else
{
Console.WriteLine("value is null");
}
Есть еще один случай, который я только что обнаружил, где if (!IsGood) { ... }
это не то же самое, что if (IsGood == false) { ... }
, Но этот нереалистичен;) Перегрузка операторов может здесь помочь:) (и оператор true/false, что AFAIK не рекомендуется в C# 2.0, потому что его предназначение состоит в том, чтобы обеспечить поведение типа bool? Для пользовательского типа и теперь Вы можете получить это со стандартным типом!)
using System;
namespace BoolHack
{
class Program
{
public struct CrazyBool
{
private readonly bool value;
public CrazyBool(bool value)
{
this.value = value;
}
// Just to make nice init possible ;)
public static implicit operator CrazyBool(bool value)
{
return new CrazyBool(value);
}
public static bool operator==(CrazyBool crazyBool, bool value)
{
return crazyBool.value == value;
}
public static bool operator!=(CrazyBool crazyBool, bool value)
{
return crazyBool.value != value;
}
#region Twisted logic!
public static bool operator true(CrazyBool crazyBool)
{
return !crazyBool.value;
}
public static bool operator false(CrazyBool crazyBool)
{
return crazyBool.value;
}
#endregion Twisted logic!
}
static void Main()
{
CrazyBool IsGood = false;
if (IsGood)
{
if (IsGood == false)
{
Console.WriteLine("Now you should understand why those type is called CrazyBool!");
}
}
}
}
}
Так что... пожалуйста, используйте перегрузку оператора с осторожностью:(
Согласно книге " Завершить код", Джефф получил свое имя и высоко ценит следующее. Вот как вы должны обращаться с логическими значениями.
if (IsGood)
if (!IsGood)
Я обычно сравниваю логические значения, но я решил, зачем добавлять дополнительный шаг к процессу и рассматривать логические значения как второсортные типы. На мой взгляд, сравнение возвращает логическое значение, а логический тип уже является логическим, так почему бы просто не использовать логическое значение.
На самом деле спор сводится к использованию хороших имен для ваших логических выражений. Как вы делали выше, я всегда формулирую свои логические объекты в вопросе. Такие как
- Это хорошо
- HasValue
- и т.п.
Техника тестирования специально против true или false определенно является плохой практикой, если рассматриваемая переменная действительно должна использоваться как логическое значение (даже если ее тип не является логическим), особенно в C/C++. Тестирование против true
может (и, вероятно, приведет) к тонким ошибкам:
Эти явно похожие тесты дают противоположные результаты:
// needs C++ to get true/false keywords
// or needs macros (or something) defining true/false appropriately
int main( int argc, char* argv[])
{
int isGood = -1;
if (isGood == true) {
printf( "isGood == true\n");
}
else {
printf( "isGood != true\n");
}
if (isGood) {
printf( "isGood is true\n");
}
else {
printf( "isGood is not true\n");
}
return 0;
}
Это отображает следующий результат:
isGood != true
isGood is true
Если вы чувствуете необходимость проверить переменную, которая используется в качестве логического флага, против true/false (что, по моему мнению, не следует делать), вы должны использовать идиому всегда проверять против false, потому что false может иметь только одно значение (0
) в то время как истина может иметь несколько возможных значений (все, кроме 0
):
if (isGood != false) ... // instead of using if (isGood == true)
Некоторые люди будут считать, что это недостаток C/C++, и это может быть правдой. Но это факт жизни в этих языках (и, вероятно, во многих других), поэтому я бы придерживался краткой идиомы, даже в таких языках, как C#, которые не позволяют использовать интегральное значение в качестве логического значения.
Посмотрите этот ТАК вопрос для примера, где эта проблема на самом деле кого-то кусала...
Я согласен с вами (и меня это тоже раздражает). Я думаю, что это лишь небольшое недопонимание того, что IsGood == true
оценивает bool
, который является то, что IsGood
должен был начать с.
Я часто вижу эти близкие случаи SomeStringObject.ToString()
,
Тем не менее, в языках, которые играют слабее с типами, это может быть оправдано. Но не в C#.
Некоторые люди считают, что явная проверка по известному значению более удобочитаема, так как вы можете определить тип переменной, прочитав. Я агностик относительно того, лучше ли один, чем другой. Они оба работают. Я считаю, что если переменная по своей сути содержит "инверсию", то я, кажется, тяготею к проверке значения:
if(IsGood) DoSomething();
или же
if(IsBad == false) DoSomething();
вместо
if(!IsBad) DoSomething();
Но опять же, это не имеет большого значения для меня, и я уверен, что это в конечном итоге, как тот же IL.
Только читабельность..
Во всяком случае, то, что вы предпочитаете, более эффективно при компиляции в машинный код. Однако я ожидаю, что они производят точно такой же машинный код.
Из ответов до сих пор, это, кажется, консенсус:
- Краткая форма лучше всего подходит в большинстве случаев. (IsGood и!IsGood)
- Булевы переменные должны быть записаны как положительные. (IsGood вместо IsBad)
- Поскольку большинство компиляторов будут выводить один и тот же код в любом случае, разницы в производительности нет, за исключением случаев интерпретируемых языков.
- Эта проблема не имеет явного победителя, вероятно, можно рассматривать как битву в религиозной войне в стиле кодирования.
Я предпочитаю использовать:
if (IsGood)
{
DoSomething();
}
а также
if (IsGood == false)
{
DoSomething();
}
как я нахожу это более читабельным! слишком легко пропустить (как при чтении, так и при наборе текста); также "если не IsGood тогда..." просто не звучит правильно, когда я слышу это, в отличие от "если IsGood ложно тогда...", что звучит лучше.
Я видел следующее как требование стиля C/C++.
if ( true == FunctionCall()) {
// stuff
}
Причина была в том, что если вы случайно поставите "=" вместо "==", компилятор возьмет на себя залог при присвоении значения константе. В то же время это ухудшает читабельность каждого оператора if.
Возможно (хотя и маловероятно, по крайней мере, я надеюсь), что в коде C TRUE и FALSE # определены для вещей, отличных от 1 и 0. Например, программист, возможно, решил использовать 0 как "true" и -1 как "false "в конкретном API. То же самое относится и к унаследованному коду C++, поскольку "true" и "false" не всегда были ключевыми словами C++, особенно в тот день, когда существовал стандарт ANSI.
Стоит также отметить, что некоторые языки, особенно такие, как Perl, JavaScript и PHP, могут по-разному интерпретировать, какие значения считаются истинными, а какие - ложными. Возможно (хотя, опять-таки, вряд ли на надежде), что "foo == false" означает что-то немного отличное от "! Foo". Этот вопрос помечен как "независимый от языка", и язык может определить оператор ==, чтобы он не работал способами, совместимыми с! оператор.
Время от времени он использует с точки зрения читабельности. Иногда именованная переменная или вызов функции могут в конечном итоге быть двойным отрицательным, что может сбить с толку, и сделать ожидаемый тест явным, как это, может помочь читаемости.
Хорошим примером этого может быть strcmp() C/C++, который возвращает 0, если строки равны, иначе <или> 0, в зависимости от того, где находится различие. Так что вы часто будете видеть:
if(strcmp(string1, string2)==0) { /*do something*/ }
Как правило, однако я согласен с вами, что
if(!isCached)
{
Cache(thing);
}
понятнее читать.
Только хуже
if (true == IsGood) {....
Никогда не понимал, что стоит за этим методом.
Я предпочитаю подход !IsGood, и я думаю, что большинство людей с языком в стиле c также предпочтут его. Я только догадываюсь здесь, но я думаю, что большинство людей, которые пишут IsGood == False, происходят из более многословного языка, такого как Visual Basic.
Для удобства чтения вы можете рассмотреть свойство, которое зависит от другого свойства:
public bool IsBad => !IsGood;
Тогда вы действительно сможете понять значение:
if (IsBad)
{
...
}
!IsGood
шаблон легче найти, чем IsGood == false
когда сводится к регулярному выражению.
/\b!IsGood\b/
против
/\bIsGood\s*==\s*false\b/
/\bIsGood\s*!=\s*true\b/
/\bIsGood\s*(?:==\s*false|!=\s*true)\b/
Я предпочитаю !IsGood
потому что для меня это понятнее и понятнее. Проверка, если boolean == true
Это избыточно, поэтому я бы этого избегал. Синтаксически, хотя я не думаю, что есть разница, если проверка IsGood == false
,
Во многих языках разница в том, что в одном случае компилятор / интерпретатор диктует значение true или false, а в другом случае это определяется кодом. C является хорошим примером этого.
if (something) ...
В приведенном выше примере "что-то" сравнивается с определением компилятора "true". Обычно это означает "не ноль".
if (something == true) ...
В приведенном выше примере "что-то" сравнивается с "истиной". Тип "истина" (и, следовательно, сопоставимость) и значение "истина" могут определяться или не быть определены языком и / или компилятором / интерпретатором.
Часто эти два не совпадают.
Если вы работаете в Perl, у вас есть возможность
unless($isGood)
Мне почему-то всегда нравилось
if (IsGood)
больше, чем
if (!IsBad)
и вот почему я вроде как Руби, если (но это слишком легко злоупотреблять):
unless (IsBad)
и даже больше, если используется так:
raise InvalidColor unless AllowedColors.include?(color)
Лично я предпочитаю форму, о которой говорит дядя Боб в Чистом коде:
(...)
if (ShouldDoSomething())
{
DoSomething();
}
(...)
bool ShouldDoSomething()
{
return IsGood;
}
где условные выражения, кроме самых тривиальных, помещаются в предикатные функции. Тогда менее важно, насколько читабельной является реализация логического выражения.
Мне кажется (хотя у меня нет доказательств, подтверждающих это), что люди, начинающие на языках типов C#/java, предпочитают метод "if (CheckSomething())", тогда как люди, начинающие на других языках (C++: конкретно Win32) C++) склонны использовать другой метод по привычке: в Win32 "if (CheckSomething())" не будет работать, если CheckSomething возвращает BOOL (вместо bool); и во многих случаях функции API явно возвращают 0/1 int/INT, а не значение true/false (то есть, что такое BOOL).
Я всегда использовал более многословный метод, опять же, по привычке. Они синтаксически одинаковы; Я не покупаю ерунду "многословие раздражает меня", потому что программист не тот, кто должен быть впечатлен кодом (компьютер делает). И в реальном мире уровень квалификации любого конкретного человека, смотрящего на написанный мною код, будет варьироваться, и у меня нет времени или желания объяснять особенности оценки высказываний тому, кто не может понять немного неважно такие биты
Я не использую ==
но иногда я использую !=
потому что это более ясно в моей голове. НО на моей работе мы не используем !=
или же ==
, Мы пытаемся получить имя, которое значимо, если с hasXYZ()
или же isABC()
,
Cybis, при кодировании на C++ вы также можете использовать ключевое слово not. Это часть стандарта с давних времен, так что этот код совершенно действителен:
if (not foo ())
bar ();
Изменить: Кстати, я забыл упомянуть, что стандарт также определяет другие логические ключевые слова, такие как и (&&), bitand (&) или (||), bitor (|), xor (^)... Они называются оператором синонимы.
Если вы действительно думаете, что вам нужно:
if (Flag == true)
тогда, поскольку условное выражение само по себе является логическим, вы, вероятно, захотите расширить его до:
if ((Flag == true) == true)
и так далее. Сколько еще гвоздей нужно этому гробу?
Ах, у меня есть кое-что в пользу более длинной формы, утверждая, что она более читаема, чем крошечная!
Я начал "исправлять" это, так как булевы значения самодостаточны, тогда я отбросил крестовый поход... ^_^ В любом случае, им здесь не нравится очистка кода, утверждая, что это затрудняет интеграцию между ветвями (это правда, но тогда ты вечно живешь с плохо выглядящим кодом...).
Если вы правильно пишете имя вашей логической переменной, оно должно выглядеть так:if (isSuccessful)
против if (returnCode)
Я мог бы заниматься булевым сравнением в некоторых случаях, например:if (PropertyProvider.getBooleanProperty(SOME_SETTING, true) == true)
потому что он читает меньше "естественно".
Эти две формы семантически идентичны и производят один и тот же машинный код, так почему бы не использовать ту, которая более читаема?
if (IsGood == false)
лучше, чем if(!IsGood)
,
При сканировании кода легко ошибиться "!" предшествующая переменная bool для символа в переменной bool.
В языке, подобном C, где нет типа "Boolean", я рекомендую более длинный путь, т.е.
if (is_good == True)
{
}
Причина в том, что это хорошо не только true
/false
(скорее всего, реализовано как символ) и, следовательно, может быть повреждено другими значениями или неправильно установлено.
Так что же хорошего в этом? Ваш код сможет подобрать любые проблемы с is_good
быть установленным неправильно, потому что без проверки == True или == False все будет означать true;) И если вы действительно имеете в виду логическое значение, то это плохо.