logical - not en c#
Una explicación clara y laica de la diferencia entre | y || Cía#? (12)
Bien, he leído sobre esto varias veces, pero aún no he escuchado una manera clara, fácil de entender (y memorable) de aprender la diferencia entre:
if (x | y)
y
if (x || y)
..en el contexto de C #. ¿Puede alguien ayudarme, por favor, a aprender esta verdad básica y cómo C # específicamente los trata de manera diferente (porque parecen hacer lo mismo)? Si la diferencia que tiene una pieza de código entre ellos es irrelevante, ¿cuál debería ser la mejor práctica por defecto?
A diferencia de lo que la mayoría de las respuestas hasta ahora dicen, el significado no es exactamente el mismo que en C ++.
Para cualquiera de las dos expresiones A y B que evalúan a booleanos, A || B y A | B hace casi lo mismo.
Un | B evalúa tanto A como B, y si uno de ellos se evalúa como verdadero, el resultado es verdadero.
A || B hace casi lo mismo, excepto que evalúa A primero, y luego solo evalúa B si es necesario. Dado que toda la expresión es verdadera si A o B son verdaderas, B no necesita ser probado en absoluto si A es verdadera. Entonces || cortocircuitos y omita la evaluación del segundo operando cuando sea posible, donde el | El operador siempre evaluará ambos.
El | el operador no se usa con frecuencia y, a menudo, no hace una diferencia. El único caso común en el que puedo pensar en dónde marcaría la diferencia es este:
if ( foo != null || foo.DoStuff()){ // assuming DoStuff() returns a bool
}
Esto funciona porque la función miembro DoStuff () nunca se llama si la prueba de la izquierda falla. Es decir, si foo es nulo, no llamamos a DoStuff en él. (Lo que nos daría una NullReferenceException).
Si hubiéramos usado el | operador, se llamaría DoStuff () independientemente de si foo era nulo o no.
En enteros, solo el | el operador está definido, y es un OR bit a bit, como describen las otras respuestas. El || sin embargo, el operador no está definido para tipos enteros, por lo que es difícil mezclarlos en C #.
A pesar de que ya se ha dicho y respondido correctamente, pensé que agregaría la respuesta de un verdadero laico ya que muchas veces eso es lo que siento en este sitio :). Además, agregaré el ejemplo de & vs. && ya que es el mismo concepto
| vs ||
Básicamente tiendes a usar el || cuando solo quiere evaluar la segunda parte SI la primera parte es FALSA. Así que esto:
if (func1() || func2()) {func3();}
es lo mismo que
if (func1())
{
func3();
}
else
{
if (func2()) {func3();}
}
Esta puede ser una manera de ahorrar tiempo de procesamiento. Si func2 () tardó mucho tiempo en procesarse, no querría hacerlo si func1 () ya fuera verdadero.
& vs &&
En el caso de & vs. && es una situación similar en la que solo evalúa la segunda parte SI la primera parte es VERDADERA. Por ejemplo esto:
if (func1() && func2()) {func3();}
es lo mismo que
if (func1())
{
if (func2()) {func3();}}
}
Esto puede ser necesario ya que func2 () puede depender de que func1 () primero sea verdadero. Si usó & y func1 () evaluado como falso, y ejecutaría func2 () de todos modos, lo que podría causar un error de tiempo de ejecución.
Jeff el laico
Buenas respuestas, pero permítanme agregar que las expresiones del lado derecho para ||
no se evalúa si la expresión del lado izquierdo es true
. Tenga esto en cuenta para los casos en que los términos de evaluación son a) intensivos en el rendimiento o b) producen efectos secundarios (raros).
Cuando se usa con operandos booleanos, el |
El operador es un operador lógico como ||
, pero la diferencia es que el ||
operador hace evaluación de cortocircuitos y el |
el operador no lo hace.
Esto significa que el segundo operando siempre se evalúa utilizando el |
operador, pero utilizando el ||
operador el segundo operando solo se evalúa si el primer operando se evalúa como falso.
El resultado de la expresión es siempre el mismo para ambos operadores, pero si la evaluación del segundo operando provoca que algo más cambie, eso solo se garantiza si usa |
operador.
Ejemplo:
int a = 0;
int b = 0;
bool x = (a == 0 || ++b != 0);
// here b is still 0, as the "++b != 0" operand was not evaluated
bool y = (a == 0 | ++b != 0);
// here b is 1, as the "++b != 0" operand was evaluated.
La evaluación de corto circuito de la ||
El operador puede usarse para escribir código más corto, ya que el segundo operando solo se evalúa si el primer operando es verdadero. En lugar de escribir así:
if (str == null) {
Console.WriteLine("String has to be at least three characters.");
} else {
if (str.Length < 3) {
Console.WriteLine("String has to be at least three characters.");
} else{
Console.WriteLine(str);
}
}
Puedes escribir así:
if (str == null || str.Length < 3) {
Console.WriteLine("String has to be at least three characters.");
} else{
Console.WriteLine(str);
}
El segundo operando solo se evalúa si el primero es falso, por lo que sabe que puede usar la referencia de cadena en el segundo operando de manera segura, ya que no puede ser nulo si se evalúa el segundo operando.
En la mayoría de los casos, querría usar el ||
operador en lugar de la |
operador. Si el primer operando es falso, no es necesario evaluar el segundo operando para obtener el resultado. Además, muchas personas (evidentemente) no saben que puedes usar el |
Operador con operandos booleanos, por lo que se confundirían al verlo utilizado de esa manera en el código.
El primer operador bit a bit funciona con dos valores numéricos y da como resultado un tercero.
Si tienes variables binarias
a = 0001001b;
b = 1000010b;
entonces
a | b == 1001011b;
Es decir, un poco en el resultado es 1 si también es 1 en cualquiera de los operandos. (Mi ejemplo usa números de 8 bits para mayor claridad)
El "tubo doble" ||, es un operador OR lógico que toma dos valores booleanos y da como resultado un tercero.
Ellos no son los mismos. Uno es OR a nivel de bits y otro es OR lógico.
X || Y, es una lógica o, significa lo mismo que "X o Y" y se aplica a valores bool. Se utiliza en condicionales o pruebas. X e Y en ese caso se pueden reemplazar con cualquier expresión que se evalúe como un valor bool. Ejemplo:
if (File.Exists("List.txt") || x > y ) { ..}
La cláusula se evalúa como verdadera si alguna de las dos condiciones es verdadera. Si la primera condición es verdadera (si el archivo existe), entonces la segunda condición no necesita y no será evaluada.
El único tubo (|) es un OR bit a bit. Para saber qué significa esto, debe comprender cómo se almacenan los números en la computadora. Supongamos que tiene una cantidad de 16 bits (Int16) que tiene el valor 15. En realidad se almacena como 0x000F (en hexadecimal) que es el mismo que 0000 0000 0000 1111 en binario. El OR a nivel de bits toma dos cantidades y los OR de cada par de bits correspondientes juntos, de modo que si el bit es 1 en cualquier cantidad, es 1 en el resultado. Por lo tanto, si a = 0101 0101 0101 0101 (que se evalúa como 0x5555 en hexadecimal) y b = 1010 1010 1010 1010 (que es 0xAAAA), entonces a | b = 1111 1111 1111 1111 = 0xFFFF.
Puede utilizar los OR (bit) de bit a bit en C # para probar si uno o más de un conjunto particular de bits está activado. Puede hacer esto si tiene, digamos, 12 valores booleanos o binarios para probar, y todos son independientes. Supongamos que tienes una base de datos de estudiantes. Un conjunto de booleanos independientes puede ser: hombre / mujer, hogar / en el campus, actual / no actual, inscrito / no inscrito, etc. En lugar de almacenar un campo booleano para cada uno de esos valores, puede almacenar Solo un bit para cada uno. El macho / hembra puede ser bit 1. inscrito / no puede ser bit 2.
Entonces puedes usar
if ((bitfield | 0x0001) == 0x0001) { ... }
como prueba para ver si no hay bits activados, excepto el bit "el estudiante es masculino", que se ignora. Eh Bien, el bit a bit OR devuelve un 1 por cada bit que está activado en cualquier número. Si el resultado del bit a bit OR arriba = 0x0001, eso significa que no hay bits activados en el campo de bits, excepto quizás el primer bit (0x0001), pero no puede decir con seguridad si el primer bit está activado, porque se enmascara
Hay un correspondiente && y &, que es lógico AND y bitwise AND. Tienen el comportamiento análogo.
Puedes usar
if ((bitfield & 0x0001) == 0x0001) { ... }
para ver si el primer bit está activado en un campo de bits.
EDIT: ¡No puedo creer que me hayan rechazado por esto!
Lo siguiente funcionaría en C / C ++ porque no tiene soporte de primera clase para booleanos, trata cada expresión con un bit "on" en ellos como verdadero, de lo contrario es falso. De hecho, el siguiente código no funcionaría en C # o Java si xey son de tipo numérico.
if (x | y)
Así que la versión explícita del código anterior es:
if ( (x | y) != 0)
En C, cualquier expresión que tenga un bit "On" en ellos, resulta verdadero
int i = 8;
if (i) // válido en C, resulta en verdadero
int alegría = -10;
if (joy) // vaild en C, resulta en verdadero
Ahora, de vuelta a C #
Si x e y son de tipo numérico, su código: if (x | y) no funcionará. ¿Has intentado compilarlo? No funcionará
Pero para su código, que podría asumir que xey son de tipo booleano, por lo que funcionará, por lo que la diferencia entre | y || para los tipos booleanos, el || está en cortocircuito, el | no es. La salida de lo siguiente:
static void Main()
{
if (x | y)
Console.WriteLine("Get");
Console.WriteLine("Yes");
if (x || y)
Console.WriteLine("Back");
Console.ReadLine();
}
static bool x
{
get { Console.Write("Hey"); return true; }
}
static bool y
{
get { Console.Write("Jude"); return false; }
}
es:
HeyJudeGet
Yes
HeyBack
Judas no se imprimirá dos veces, el || es un operador booleano, muchos lenguajes derivados de C operadores booleanos están cortocircuitados , las expresiones booleanas son más eficaces si están cortocircuitadas.
En cuanto a los términos laicos, cuando dice cortocircuito, por ejemplo en || (u operador), si la primera expresión ya es verdadera, no es necesario evaluar la segunda expresión. Ejemplo: si (respuesta == ''y'' || respuesta == ''Y''), si el usuario presiona y pequeña, el programa no necesita evaluar la segunda expresión (respuesta == ''Y''). Eso es un cortocircuito.
En mi código de ejemplo anterior, X es verdadera, por lo que la Y en || el operador no se evaluará más, por lo que no hay una segunda salida de "Jude".
No use este tipo de código en C # incluso si X e Y son de tipo booleano: if (x | y) . No ejecutante.
Recomiendo encarecidamente leer this artículo de Dotnet Mob
Para la operación lógica OR, si alguno de sus operandos se evalúa como verdadero, toda la expresión se evalúa como verdadera
esto es lo que || El operador lo hace: omite la evaluación restante cuando encuentra un verdadero. Mientras que | El operador evalúa sus operandos completos para evaluar el valor de la expresión completa.
if(true||Condition1())//it skip Condition1()''s evaluation
{
//code inside will be executed
}
if(true|Condition1())//evaluates Condition1(), but actually no need for that
{
//code inside will be executed
}
Es mejor usar la versión de circuito corto del operador lógico, ya sea un operador OR (||) o AND (&&).
Considere el siguiente fragmento de códigoint i=0;
if(false||(++i<10))//Now i=1
{
//Some Operations
}
if(true||(++i<10))//i remains same, ie 1
{}
Este efecto se llama efecto secundario , que en realidad se ve en el lado derecho de la expresión en operadores lógicos en cortocircuito
Referencia: this
Sin profundizar en los detalles de ninguna manera, forma o forma, aquí está la versión de un verdadero laico.
Piensa en "|" como una recta o en inglés; pensar en "||" como "o bien" en inglés.
Del mismo modo, piense en "&" como "y" en inglés; piensa en "&&" como "y también" en inglés.
Si lees una expresión a ti mismo usando estos términos, a menudo tienen mucho más sentido.
Tuve la misma pregunta pero no entendí las respuestas por completo hasta que encontré esta página que lo explica todo muy bien y da ejemplos muy buenos: http://www.codeproject.com/Articles/544990/Understand-how-bitwise-operators-work-Csharp-and-V
| es un operador OR a nivel de bit (numérico, entero). funciona al convertir los números en binarios y hacer un OR para cada uno de los dígitos correspondientes. de nuevo, los números ya están representados en binario en la computadora, por lo que no se realiza tal conversión en tiempo de ejecución;)
|| es un operador OR lógico (booleano). solo funciona en valores verdaderos y falsos
||
Es el operador -lógico . Ver here Se evalúa como true
si al menos uno de los operandos es verdadero. Solo puedes usarlo con operandos booleanos; Es un error usarlo con operandos enteros.
// Example
var one = true || bar(); // result is true; bar() is never called
var two = true | bar(); // result is true; bar() is always called
|
es el operador o Ver here Si se aplica a tipos booleanos, se evalúa como true
si al menos uno de los operandos es verdadero. Si se aplica a tipos enteros, se evalúa a otro número. Este número tiene cada uno de sus bits establecido en 1 si al menos uno de los operandos tiene un conjunto de bits correspondiente.
// Example
var a = 0x10;
var b = 0x01;
var c = a | b; // 0x11 == 17
var d = a || b; // Compile error; can''t apply || to integers
var e = 0x11 == c; // True
Para los operandos booleanos, a || b
a || b
es idéntico a a | b
a | b
, con la única excepción de que b
no se evalúa si a
es verdadero. Por este motivo, ||
se dice que es "cortocircuito".
Si la diferencia que tiene una pieza de código entre ellos es irrelevante, ¿cuál debería ser la mejor práctica por defecto?
Como se señaló, la diferencia no es irrelevante, por lo que esta pregunta es parcialmente discutible. En cuanto a las "mejores prácticas", no hay una: simplemente use el operador que sea correcto para usar. En general, la gente favorece ||
sobre |
para operandos booleanos, ya que puede estar seguro de que no producirá efectos secundarios innecesarios.