Pregunta

En C# (y no dude en responder para otros lenguajes), ¿en qué orden el tiempo de ejecución evalúa una declaración lógica?

Ejemplo:

DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
    //do some stuff with myDt
}

¿Qué declaración evalúa primero el tiempo de ejecución?

myDt != null

o:

myDt.Rows.Count > 0

?

¿Hay algún momento en el que el compilador evalúe la declaración al revés?¿Quizás cuando está involucrado un operador "OR"?


& se conoce como operador lógico bit a bit y siempre evaluará todas las subexpresiones

¿Cuál es un buen ejemplo de cuándo utilizar el operador bit a bit en lugar del "booleano en cortocircuito"?

¿Fue útil?

Solución

C# :De izquierda a derecha y el procesamiento se detiene si se encuentra una no coincidencia (se evalúa como falso).

Otros consejos

"C# :De izquierda a derecha y el procesamiento se detiene si se encuentra una coincidencia (evaluada como verdadera).

La oveja zombie está equivocada, no hay suficiente representante para rechazarla.

La pregunta es sobre el operador &&, no el || operador.

En el caso de && la evaluación se detendrá si se encuentra un FALSO.

En el caso de || La evaluación se detiene si se encuentra una verdadera.

Me doy cuenta de que esta pregunta ya ha sido respondida, pero me gustaría brindar más información relacionada con el tema.

En idiomas, como C ++, donde realmente puede sobrecargar el comportamiento de && y || operadores, es muy recomendable que no hagas esto.Esto se debe a que cuando sobrecargas este comportamiento, terminas forzando la evaluación de ambos lados de la operación.Esto hace dos cosas:

  1. Rompe el mecanismo de evaluación diferida porque la sobrecarga es una función que debe invocarse y, por lo tanto, ambos parámetros se evalúan antes de llamar a la función.
  2. El orden de evaluación de dichos parámetros no está garantizado y puede ser específico del compilador.Por lo tanto, los objetos no se comportarían de la misma manera que en los ejemplos enumerados en la pregunta/respuestas anteriores.

Para obtener más información, lea el libro de Scott Meyers, C++ más eficaz.¡Salud!

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. La evaluación se realiza de izquierda a derecha.
  2. Y también El operador se asegura de que solo si el lado izquierdo es VERDADERO, se evaluará el lado derecho (muy importante, ya que si x no es nada, x.go fallará)

Puedes utilizar Y en lugar deAndTambién en vb.en cuyo caso el lado izquierdo también se evalúa primero, pero el lado derecho se evaluará independientemente del resultado.

Mejores prácticas:Utilice siempre AndAlso, a menos que tenga una muy buena razón para no hacerlo.


En un seguimiento se preguntó por qué o cuándo alguien usaría And en lugar de AndAlso (o & en lugar de &&):Aquí hay un ejemplo:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

En este caso, quiero iniciar tanto X como Y.Y debe inicializarse para que y.DoDance pueda ejecutarse.Sin embargo, en la función init() también estoy haciendo algunas cosas adicionales como verificar que un socket esté abierto, y solo si eso funciona bien, por ejemplo. ambos, debería seguir adelante y hacer el x.process(y).

Nuevamente, esto probablemente no sea necesario y no sea elegante en el 99% de los casos, es por eso que dije que el valor predeterminado debería ser usar Y también.

@shsteimer

El concepto al que se refiere la modestia es el de sobrecarga del operador.en el comunicado:...A se evalúa primero, si se evalúa como falso, B nunca se evalúa.Lo mismo se aplica a

Eso no es una sobrecarga del operador.La sobrecarga de operadores es el término dado para permitirle definir un comportamiento personalizado para los operadores, como *, +, =, etc.

Esto le permitiría escribir su propia clase 'Registro' y luego hacer

a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.

Haciendo esto

a() || b() // be never runs if a is true

en realidad se llama Evaluación de cortocircuito

ZombieSheep está en lo cierto.El único "problema" que podría estar esperando es que esto sólo es cierto si está utilizando el operador &&.Cuando se utiliza el operador &, ambas expresiones se evaluarán cada vez, independientemente de si una o ambas se evalúan como falsa.

if (amHungry & whiteCastleIsNearby)
{
   // The code will check if White Castle is nearby
   // even when I am not hungry
}

if (amHungry && whiteCastleIsNearby)
{
   // The code will only check if White Castle is nearby
   // when I am hungry
}

Tenga en cuenta que existe una diferencia entre && y & con respecto a la cantidad de expresión que se evalúa.

&& se conoce como AND booleano en cortocircuito y, como lo señalaron otros aquí, se detendrá antes de tiempo si el resultado se puede determinar antes de que se evalúen todas las subexpresiones.

& se conoce como operador lógico bit a bit y siempre evaluará todas las subexpresiones.

Como tal:

if (a() && b())

sólo llamará b si a devoluciones verdadero.

sin embargo, esto:

if (a() & b())

Siempre llamará a ambos a y b, aunque el resultado de llamar a es falso y por lo tanto se sabe que lo es FALSO independientemente del resultado de la llamada b.

Esta misma diferencia existe para el || y | operadores.

Algunos lenguajes tienen situaciones interesantes en las que las expresiones se ejecutan en un orden diferente.Estoy pensando específicamente en Ruby, pero estoy seguro de que lo tomaron prestado de otro lugar (probablemente Perl).

Las expresiones en la lógica permanecerán de izquierda a derecha, pero por ejemplo:

puts message unless message.nil?

Lo anterior evaluará "¿Message.nil?" Primero, luego, si se evalúa en falso (a menos que sea como si excepto se ejecuta cuando la condición es falsa en lugar de verdadera), se ejecutará el mensaje ", lo que imprime el contenido de la variable de mensaje en la pantalla.

A veces es una forma interesante de estructurar el código...Personalmente, me gusta usarlo para líneas 1 muy cortas como la anterior.

Editar:

Para que quede un poco más claro, lo anterior es lo mismo que:

unless message.nil?
  puts message
end

El de la izquierda se detiene si es nulo.

Editar:En vb.net evaluará ambos y posiblemente arrojará un error, a menos que use AndAlso

El concepto al que se refiere la modestia es el de sobrecarga del operador.en el comunicado:

if( A && B){
    // do something
}

A se evalúa primero, si se evalúa como falso, B nunca se evalúa.Lo mismo se aplica a

if(A || B){
    //do something
}

A se evalúa primero, si se evalúa como verdadero, B nunca se evalúa.

Este concepto de sobrecarga se aplica (creo) a todos los lenguajes de estilo C, y también a muchos otros.

No, al menos el compilador de C# no funciona al revés (ni en && ni en ||).Es de izquierda a derecha.

Cuando todo está en línea, se ejecuta de izquierda a derecha.

Cuando las cosas están anidadas, se ejecutan de adentro hacia afuera.Esto puede parecer confuso ya que normalmente lo "más interno" está en el lado derecho de la línea, por lo que parece que va hacia atrás...

Por ejemplo

a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );

Las cosas suceden así:

  • Llamar GetAddress con lo literal "Orion"
  • Llamar GetSummary con lo literal "Orion" y el resultado de GetAddress
  • Llamar Foo con lo literal 5 y el resultado de GetSummary
  • Asigne este valor a a

Me gustan las respuestas de Orión.Agregaré dos cosas:

  1. La izquierda a derecha todavía se aplica primero
  2. El interior al exterior para garantizar que todos los argumentos se resuelvan antes de llamar a la función.

Digamos que tenemos el siguiente ejemplo:

a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
           GetSummary("Chris", GetAddress("Chris")));

Aquí está el orden de ejecución:

  1. GetAddress("Orion")
  2. GetSummary("Orion", ...)
  3. GetAddress("Chris")
  4. GetSummary("Chris", ...)
  5. Foo(...)
  6. Asigna a a

No puedo hablar sobre los requisitos legales de C# (aunque probé un ejemplo similar usando Mono antes de escribir esta publicación), pero este orden está garantizado en Java.

Y solo para completar (dado que este también es un hilo independiente del lenguaje), hay lenguajes como C y C++, donde el orden no está garantizado a menos que haya un punto de secuencia.Referencias: 1, 2.Sin embargo, al responder a la pregunta del hilo, && y || son puntos de secuencia en C++ (a menos que estén sobrecargados;consulte también la excelente respuesta de OJ).Entonces algunos ejemplos:

  • foo() && bar()
  • foo() & bar()

En el && caso, foo() está garantizado que se ejecutará antes bar() (si es que este último se ejecuta), ya que && es un punto de secuencia.En el & En este caso, no se ofrece tal garantía (en C y C++) y, de hecho, bar() puede correr antes foo(), o viceversa.

¿Cuál es un buen ejemplo de cuándo utilizar el operador bit a bit en lugar del "booleano en cortocircuito"?

Supongamos que tiene indicadores, por ejemplo para atributos de archivos.Supongamos que ha definido READ como 4, WRITE como 2 y EXEC como 1.En binario, eso es:

READ  0100  
WRITE 0010  
EXEC  0001

Cada bandera tiene un bit establecido y cada una es única.Los operadores bit a bit le permiten combinar estos indicadores:

flags = READ & EXEC; // value of flags is 0101

He oído en alguna parte que los compiladores funcionan al revés, pero no estoy seguro de qué tan cierto es esto.

Utiliza & cuando desea evaluar específicamente todas las subexpresiones, muy probablemente porque tienen los efectos secundarios que desea, aunque el resultado final será FALSO y así no ejecutar tu entonces parte de tu si-declaración.

Tenga en cuenta que & y | opera tanto para máscaras bit a bits como para valores booleanos y no es solo para operaciones bit a bit.Ellos son llamado bit a bit, pero están definidos para tipos de datos enteros y booleanos en C#.

@csmba:

En un seguimiento se preguntó por qué o cuándo alguien usaría And en lugar de AndAlso (o & en lugar de &&):Aquí hay un ejemplo:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

En este caso, quiero iniciar tanto X como Y.Y debe inicializarse para que y.DoDance pueda ejecutarse.Sin embargo, en la función init() también estoy haciendo algo adicional como verificar que un socket esté abierto, y solo si funciona bien, para ambos, debo seguir adelante y hacer el proceso x.process(y).

Creo que esto es bastante confuso.Aunque su ejemplo funciona, no es el caso típico de usar And (y probablemente escribiría esto de otra manera para que quede más claro). And (& en la mayoría de los demás idiomas) es en realidad la operación bit a bit.Lo usaría para calcular operaciones de bits, por ejemplo, eliminar un bit de bandera o enmascarar y probar banderas:

Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
    MsgBox("The text will be set in italic.")
End If

El lenguaje de programación D sí lo hace. evaluación de izquierda a derecha con cortocircuito y no permitir la sobrecarga del && y '||' operadores.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top