visual operator not net equal language-agnostic boolean not-operator

language agnostic - operator - ¿Debo usar `! IsGood` o` IsGood== false`?



relational operators vba (30)

Sigo viendo código que hace controles como este

if (IsGood == false) { DoSomething(); }

o esto

if (IsGood == true) { DoSomething(); }

Odio esta sintaxis, y siempre uso la siguiente sintaxis.

if (IsGood) { DoSomething(); }

o

if (!IsGood) { DoSomething(); }

¿Hay alguna razón para usar '' == true '' o '' == false ''?

¿Es una cosa de legibilidad? ¿La gente simplemente no comprende las variables booleanas?

Además, ¿hay alguna diferencia de rendimiento entre los dos?


De las respuestas hasta ahora, este parece ser el consenso:

  1. La forma corta es mejor en la mayoría de los casos. (IsGood y! IsGood)
  2. Las variables booleanas deben escribirse como positivas. (IsGood en lugar de IsBad)
  3. Dado que la mayoría de los compiladores emitirán el mismo código de cualquier manera, no hay diferencia en el rendimiento, excepto en el caso de los idiomas interpretados.
  4. Este problema no tiene un ganador claro, probablemente podría ser visto como una batalla en la guerra religiosa de estilo de codificación.

Por alguna razón siempre me ha gustado

if (IsGood)

mas que

if (!IsBad)

y es por eso que me gusta menos Ruby''s (pero es un poco demasiado fácil de abusar):

unless (IsBad)

y aún más si se usa así:

raise InvalidColor unless AllowedColors.include?(color)


Prefiero usar:

if (IsGood) { DoSomething(); }

y

if (IsGood == false) { DoSomething(); }

como me parece más legible, ¡el! es demasiado fácil pasar por alto (en lectura y mecanografía); también "si no es bueno entonces ..." no suena bien cuando lo escucho, en lugar de "si IsGood es falso, entonces ...", que suena mejor.


¡Ah, he colaborado un poco a favor de la forma más larga, argumentando que es más fácil de leer que la pequeña!

Empecé a "arreglar" eso, dado que los booleanos son autosuficientes, entonces abandoné la cruzada ... ^ _ ^ No les gusta limpiar el código aquí, de todos modos, argumentando que dificulta la integración entre ramas (eso es cierto, pero entonces vives para siempre con un código malicioso ...).

Si escribe correctamente su nombre de variable booleana, debería leer de forma natural:
if (isSuccessful) vs. if (returnCode)

En algunos casos, me puedo permitir una comparación booleana, como:
if (PropertyProvider.getBooleanProperty(SOME_SETTING, true) == true) porque lee menos "naturalmente".


Algunas personas consideran que la comprobación explícita contra un valor conocido es más legible, ya que puede inferir el tipo de variable leyendo. Soy agnóstico en cuanto a si uno es mejor que el otro. Ambos trabajan. Encuentro que si la variable posee inherentemente un "inverso", entonces parece que gravito hacia la comprobación contra un valor:

if(IsGood) DoSomething();

o

if(IsBad == false) DoSomething();

en lugar de

if(!IsBad) DoSomething();

Pero, de nuevo, no me importa mucho, y estoy seguro de que termina siendo la misma IL.


Cybis, al codificar en C ++ también puede usar la palabra clave no . Es parte del estándar desde hace mucho tiempo, por lo que este código es perfectamente válido:

if (not foo ()) bar ();

Editar: Por cierto, olvidé mencionar que el estándar también define otras palabras clave booleanas como y (&&), bitand (&), o (||), bitor (|), xor (^) ... Se les llama operador sinónimos.


De acuerdo con Code Complete, un libro del que Jeff obtuvo su nombre y tiene en gran estima, la siguiente es la forma en que debes tratar los booleanos.

if (IsGood) if (!IsGood)

Utilizo para comparar realmente los booleanos, pero calculé por qué agregar un paso adicional al proceso y tratar los booleanos como tipos de segunda tasa. En mi opinión, una comparación devuelve un valor booleano y un tipo booleano ya es un valor booleano, así que ¿por qué no utilizar el booleano?

Realmente, el debate se basa en usar buenos nombres para tus booleanos. Como hiciste arriba, siempre expreso mis objetos booleanos para una pregunta. Como

  • Es bueno
  • HasValue
  • etc.

El patrón !IsGood es más difícil de encontrar que IsGood == false cuando se lo reduce a una expresión regular.

//b!IsGood/b/

vs

//bIsGood/s*==/s*false/b/ //bIsGood/s*!=/s*true/b/ //bIsGood/s*(?:==/s*false|!=/s*true)/b/


En muchos idiomas, la diferencia es que, en un caso, el compilador / intérprete debe dictar el significado de verdadero o falso, mientras que en el otro caso, está siendo definido por el código. C es un buen ejemplo de esto.

if (something) ...

En el ejemplo anterior, "algo" se compara con la definición del compilador de "verdadero". Por lo general, esto significa "no cero".

if (something == true) ...

En el ejemplo anterior, "algo" se compara con "verdadero". Tanto el tipo de "verdadero" (y por lo tanto la comparabilidad) como el valor de "verdadero" pueden o no estar definidos por el lenguaje y / o el compilador / intérprete.

A menudo los dos no son lo mismo.


Es posible (aunque poco probable, al menos eso espero) que en el código C TRUE y FALSE estén # definidos para cosas distintas de 1 y 0. Por ejemplo, un programador podría haber decidido usar 0 como "verdadero" y -1 como "falso" "en una API particular. Lo mismo ocurre con el código de C ++ heredado, ya que "verdadero" y "falso" no siempre eran palabras clave de C ++, sobre todo el día antes de que existiera el estándar ANSI.

También vale la pena señalar que algunos lenguajes, especialmente los de script, como Perl, JavaScript y PHP, pueden tener interpretaciones divertidas de qué valores cuentan como verdaderos y qué valores cuentan como falsos. Es posible (aunque, de nuevo, improbable para las esperanzas) que "foo == false" signifique algo sutilmente diferente de "! Foo". Esta pregunta está etiquetada como "independiente del idioma", y un lenguaje puede definir el operador == para que no funcione de manera compatible con el! operador.


Estoy de acuerdo contigo (y también me molesta). Creo que es solo un pequeño malentendido que IsGood == true evalúa a un bool, que es para lo que IsGood era para empezar.

A menudo veo estas instancias cercanas de SomeStringObject.ToString() .

Dicho esto, en los idiomas que juegan más flojos con los tipos, esto podría estar justificado. Pero no en C #.


He visto lo siguiente como un requisito de estilo C / C ++.

if ( true == FunctionCall()) { // stuff }

El razonamiento fue que si colocaba accidentalmente "=" en lugar de "==", el compilador bloqueará la asignación de un valor a una constante. Mientras tanto, hiere la legibilidad de cada declaración única.


La única vez que puedo pensar dónde tenía sentido el código más veraz era en pre.NET Visual Basic donde verdadero y falso eran en realidad enteros (verdadero = -1, falso = 0) y las expresiones booleanas se consideraban falsas si se evaluaban a cero y verdadero para cualquier otro valor distinto de cero. Entonces, en el caso del viejo VB, los dos métodos enumerados en realidad no eran equivalentes y si solo quería que algo fuera cierto si se evaluaba a -1, tenía que comparar explícitamente con ''verdadero''. Entonces, una expresión que evalúa "+1" sería verdadera si se evaluara como un número entero (porque no es cero) pero no sería equivalente a ''verdadero''. No sé por qué VB se diseñó de esa manera, pero veo muchas expresiones booleanas que comparan las variables con verdadero y falso en el código anterior de VB.


Legibilidad solo ..

Si algo de la manera que prefiera es más eficiente cuando se compila en código máquina. Sin embargo, espero que produzcan exactamente el mismo código de máquina.


Lo único peor es

if (true == IsGood) {....

Nunca entendí el pensamiento detrás de ese método.


Me parece (aunque no tengo pruebas para respaldar esto) que las personas que comienzan en C # / idiomas tipo java prefieren el método "if (CheckSomething ())", mientras que las personas que comienzan en otros idiomas (C ++: específicamente Win32 C ++) tienden a usar el otro método por costumbre: en Win32 "if (CheckSomething ())" no funcionará si CheckSomething devuelve un BOOL (en lugar de un bool); y en muchos casos, las funciones de API devuelven explícitamente un 0/1 int / INT en lugar de un valor verdadero / falso (que es lo que es un BOOL).

Siempre he usado el método más detallado, de nuevo, por costumbre. Son sintácticamente iguales; No compro la tontería de "la verbosidad me irrita", porque el programador no es el que necesita ser impresionado por el código (la computadora lo hace). Y, en el mundo real, el nivel de habilidad de cualquier persona que mire el código que he escrito variará, y no tengo el tiempo o la inclinación para explicar las peculiaridades de la evaluación de la declaración a alguien que puede no entender poco importante bits como ese.


Ocasionalmente tiene usos en términos de legibilidad. En ocasiones, una variable o llamada de función determinada puede terminar siendo un doble negativo, lo que puede ser confuso, y hacer que la prueba esperada sea explícita de esta manera puede facilitar la lectura.

Un buen ejemplo de esto podría ser strcmp () C / C ++ que devuelve 0 si las cadenas son iguales, de lo contrario <o> 0, dependiendo de dónde esté la diferencia. Entonces, a menudo verá:

if(strcmp(string1, string2)==0) { /*do something*/ }

Sin embargo, en general estoy de acuerdo con usted en que

if(!isCached) { Cache(thing); }

es más claro de leer.


Para facilitar la lectura, podría considerar una propiedad que dependa de la otra propiedad:

public bool IsBad get { { return !IsGood; } }

Entonces, puedes entender el significado:

if(IsBad) { ... }


Personalmente, prefiero la forma de la que habla el tío Bob en Clean Code:

(...) if (ShoouldDoSomething()) { DoSomething(); } (...) bool ShouldDoSomething() { return IsGood; }

donde los condicionales, excepto los más triviales, se ponen en funciones predicativas. Entonces importa menos qué tan legible sea la implementación de la expresión booleana.


Prefiero el enfoque ! IsGood , y creo que la mayoría de las personas que provienen de un entorno lingüístico de estilo c también lo preferirán. Solo estoy adivinando aquí, pero creo que la mayoría de las personas que escriben IsGood == False provienen de un fondo de lenguaje más detallado como Visual Basic.


Prefiero! Es bueno porque para mí, es más claro y conciso. Sin embargo, verificando si un valor booleano == verdadero es redundante, así lo evitaría. Sin embargo, sintácticamente, no creo que haya una diferencia comprobando si IsGood == falso.


Siempre me río (o lanzo algo a alguien, dependiendo de mi estado de ánimo) cuando me encuentro con

if (someBoolean == true) { /* ... */ }

porque seguramente si no puede confiar en el hecho de que su comparación arroja un valor booleano, entonces tampoco puede confiar en comparar el resultado con el valor verdadero, por lo que el código debería convertirse en

if ((someBoolean == true) == true) { /* ... */ }

pero, por supuesto, esto realmente debería ser

if (((someBoolean == true) == true) == true) { /* ... */ }

pero por supuesto ...

(ah, la compilación falló. Volver al trabajo)


Sigo la misma sintaxis que tú, es menos detallado.

Las personas (más principiantes) prefieren usar == verdadero solo para asegurarse de que es lo que quieren. Se usan para usar el operador en su condición ... lo encontraron más legible. Pero una vez que se hizo más avanzado, lo encontró irritante porque es demasiado detallado.



Tendemos a hacer lo siguiente aquí:

if(IsGood)

o

if(IsGood == false)

La razón de esto es porque tenemos un código heredado escrito por un tipo que ya no está aquí (en Delphi) que se ve así:

if not IsNotGuam then

Esto nos ha causado mucho dolor en el pasado, por lo que se decidió que siempre trataríamos de verificar lo positivo; si eso no fuera posible, entonces compare lo negativo con lo falso.


Yo preferiría una variante más corta . Pero a veces == false ayuda a que tu código sea aún más corto:

Para el escenario de la vida real en proyectos que usan C # 2.0, solo veo una buena razón para hacer esto: bool? tipo. Tres estados bool? es útil y es fácil verificar uno de sus posibles valores de esta manera.

En realidad, no puedes usar (!IsGood) si IsGood es bool? . Pero escribir (IsGood.HasValue && IsGood.Value) es peor que (IsGood == true) .

Juega con esta muestra para tener una idea:

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"); }

Hay un caso más que acabo de descubrir en el que if (!IsGood) { ... } no es lo mismo que if (IsGood == false) { ... } . Pero este no es realista;) La sobrecarga del operador puede ayudar aquí :) (y el operador verdadero / falso que AFAIK se desaconseja en C # 2.0 porque su propósito es proporcionar un comportamiento tipo bool para el tipo definido por el usuario y ahora ¡puedes obtenerlo con el tipo estándar!)

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!"); } } } } }

Entonces ... por favor, use la sobrecarga del operador con precaución :(


¡No uso == pero alguna vez uso! = Porque está más claro en mi mente. PERO en mi trabajo no usamos! = O ==. Intentamos obtener un nombre que sea significativo con hasXYZ () o isABC ().


Si realmente crees que necesitas:

if (Flag == true)

luego, dado que la expresión condicional es en sí misma booleana, es probable que desee expandirla a:

if ((Flag == true) == true)

y así. ¿Cuántas uñas más necesita este ataúd?


Si trabaja en Perl, tiene la opción de

unless($isGood)


La técnica de probar específicamente contra verdadero o falso es definitivamente una mala práctica si se supone que la variable en cuestión se debe usar como un valor booleano (incluso si su tipo no es booleano), especialmente en C / C ++. Las pruebas en contra de la true pueden (y probablemente lo harán) conducir a errores sutiles:

Estas pruebas aparentemente similares dan resultados opuestos:

// 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; }

Esto muestra el siguiente resultado:

isGood != true isGood is true

Si sientes la necesidad de probar la variable que se usa como indicador booleano contra verdadero / falso (lo cual no debería hacerse en mi opinión), debes usar el modismo de probar siempre contra falso porque falso puede tener solo un valor ( 0 ) mientras que un verdadero puede tener múltiples valores posibles (cualquier cosa que no sea 0 ):

if (isGood != false) ... // instead of using if (isGood == true)

Algunas personas tendrán la opinión de que esto es un defecto en C / C ++, y eso puede ser cierto. Pero es un hecho de la vida en esos idiomas (y probablemente en muchos otros), por lo que me quedaría con el idioma corto, incluso en idiomas como C # que no le permiten usar un valor integral como booleano.

Vea esta pregunta SO para un ejemplo de donde este problema realmente mordió a alguien ...