2009-07-23 19 views
76

¿Cuál es la diferencia entre o y OrElse?O frente a OrElse

if temp is dbnull.value or temp = 0 

produce el error:

Operator '=' is not defined for type 'DBNull' and type 'Integer'.

mientras éste funciona como un encanto !?

if temp is dbnull.value OrElse temp = 0 

Respuesta

114

OrElse es un en cortocircuito operador, Or no lo es.

Según la definición del operador booleano 'o', si el primer término es verdadero, entonces el todo es definitivamente cierto, por lo que no es necesario evaluar el segundo término.

OrElse sabe esto, así que no intenta y evaluar temp = 0 una vez que se estableció que temp Is DBNull.Value

Or no sabe esto, y siempre intentar evaluar ambos términos. Cuando temp Is DBNull.Value, no se puede comparar con cero, se cae.

Deberías usar ... bueno, cualquiera tiene sentido.

+2

Entonces, ¿O tiene sentido cuando llamo a una función después de la o que tiene efectos secundarios de los que depende mi código? –

+2

O tiene sentido en todos los casos donde el segundo elemento no activa el error si el primero es verdadero ... – awe

+3

@ malach: Supongo que sí (realmente obtienes el comportamiento de OrElse en muchos otros idiomas): No es una buena idea para llamar funciones con efectos secundarios en condicionales compuestos hace que el código sea ilegible. – Utaal

4

(He mirado en otras respuestas y se dio cuenta que estaba mal, muy mal)

El operador OrElse "realiza disyunción lógica de cortocircuito en dos expresiones", es decir: si el operando de la izquierda es verdadero y lo que toda la expresión está garantizada para ser verdad ni siquiera se puede evaluar el operando derecho (esto es útil en casos como:.

string a; 
//... 
if (a is null) or (a = "Hi") //... 

para evitar un tiro NullReferenceException por el operador de la derecha

Estoy sinceramente sorprendido de que esto (evaluación perezosa) no es el comportamiento por defecto de or y and como lo es en C/C++ y C# (y muchos otros idiomas ...)

+7

La cosa es que, en VB classic, había * solo * Y y O, que no eran de cortocircuito. Creo ** Tengo razón al decir que las primeras versiones de VB.NET realmente cambiaron el comportamiento de estos operadores: hubo un alboroto, por lo que se cambiaron de nuevo y se introdujeron también AndAlso y OrElse (cortocircuito). Solo puedo imaginar los nombres alternativos que deben haber considerado si estos fueran los mejores ... – AakashM

+1

Al proporcionar Or y OrElse (| y || en C#), esto permite al desarrollador elegir cómo manejar su propio código. Usando el código anterior, tendría que usar una captura de prueba para manejar un valor nulo en la variable a. OrElse permite que el desarrollador maneje esto en el resto de la declaración if como un posible resultado conocido en lugar de una excepción. Esto es más obvio si la variable a era un parámetro en un método, donde tiene menos control sobre cuándo a la variable se le asigna un valor (es decirfuera del método) –

8

OrElse es en cortocircuito, esto significa que solo se probará un lado de la expresión si el primer lado coincide.

Al igual que AndAlso solo probará un lado de la expresión si la primera mitad es un error.

33

Este es el mismo comportamiento que con C#, donde todo el mundo utiliza el Coditional O (||) y el condicional y (& &), donde también tiene la normal o (|) y normal Y (&). Entonces, comparando C# con VB.La red es:

| => O

|| => OrElse

& => Y

& & => AndAlso

Los operadores booleanos condifitonal Son muy útiles impidiendo anidado si las construcciones. Pero a veces los operadores booleanos normales son necesarios para asegurar el acceso a ambas rutas de código.

+5

En realidad, nunca supe que esto estaba disponible. Gracias por nueva información. Es bueno saberlo, aunque realmente no puedo ver ninguna situación en la que me gustaría usar "|". ¡Creo que requeriría la segunda condición para que los efectos secundarios tengan sentido, y eso en sí mismo tiene poco sentido en mi opinión! ;) – Kjartan

+3

Eh, que yo sepa, '|' y '&' son operadores bit a bit en C#, no operaciones booleanas en absoluto. – Nyerguds

4

La respuesta de Bert no es muy precisa. El '|' o '&' es operador lógico, en C#, que siempre tratan como operador de bits, consulte el siguiente código como ejemplo

 static void Main() 
     { 
      object a = null; 
      int b = 3; 
      if (a == null | a.ToString() == "sdffd") 
      { 
       Console.WriteLine("dddd"); 
      } 
      Console.WriteLine(b | b); 
      Console.Read(); 
     } 

La siguiente es IL

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  62 (0x3e) 
    .maxstack 3 
    .locals init ([0] object a, 
      [1] int32 b, 
      [2] bool CS$4$0000) 
    IL_0000: nop 
    IL_0001: ldnull 
    IL_0002: stloc.0 
    IL_0003: ldc.i4.3 
    IL_0004: stloc.1 
    IL_0005: ldloc.0 
    IL_0006: ldnull 
    IL_0007: ceq 
    IL_0009: ldloc.0 
    IL_000a: callvirt instance string [mscorlib]System.Object::ToString() 
    IL_000f: ldstr  "sdffd" 
    IL_0014: call  bool [mscorlib]System.String::op_Equality(string, 
                   string) 
    IL_0019: or 
    IL_001a: ldc.i4.0 
    IL_001b: ceq 
    IL_001d: stloc.2 
    IL_001e: ldloc.2 
    IL_001f: brtrue.s IL_002e 
    IL_0021: nop 
    IL_0022: ldstr  "dddd" 
    IL_0027: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_002c: nop 
    IL_002d: nop 
    IL_002e: ldloc.1 
    IL_002f: ldloc.1 
    IL_0030: or 
    IL_0031: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0036: nop 
    IL_0037: call  int32 [mscorlib]System.Console::Read() 
    IL_003c: pop 
    IL_003d: ret 
    } // end of method Program::Main 

cuando se utiliza || para probar "un nulo ==" y "a.ToString() == 'sdffd', la IL será

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    // Code size  63 (0x3f) 
    .maxstack 2 
    .locals init ([0] object a, 
      [1] int32 b, 
      [2] bool CS$4$0000) 
    IL_0000: nop 
    IL_0001: ldnull 
    IL_0002: stloc.0 
    IL_0003: ldc.i4.3 
    IL_0004: stloc.1 
    IL_0005: ldloc.0 
    IL_0006: brfalse.s IL_001d 
    IL_0008: ldloc.0 
    IL_0009: callvirt instance string [mscorlib]System.Object::ToString() 
    IL_000e: ldstr  "sdffd" 
    IL_0013: call  bool [mscorlib]System.String::op_Equality(string, 
                   string) 
    IL_0018: ldc.i4.0 
    IL_0019: ceq 
    IL_001b: br.s  IL_001e 
    IL_001d: ldc.i4.0 
    IL_001e: stloc.2 
    IL_001f: ldloc.2 
    IL_0020: brtrue.s IL_002f 
    IL_0022: nop 
    IL_0023: ldstr  "dddd" 
    IL_0028: call  void [mscorlib]System.Console::WriteLine(string) 
    IL_002d: nop 
    IL_002e: nop 
    IL_002f: ldloc.1 
    IL_0030: ldloc.1 
    IL_0031: or 
    IL_0032: call  void [mscorlib]System.Console::WriteLine(int32) 
    IL_0037: nop 
    IL_0038: call  int32 [mscorlib]System.Console::Read() 
    IL_003d: pop 
    IL_003e: ret 
} // end of method Program::Main 

ahora se puede ver la diferencia, por favor, no creo que la '|' o 'y' como operador condicional, es solo un operador lógico, no creo que sea necesario usarlo para juzgar la condición

+2

'El '|' o '&' es operador lógico, en C#, siempre lo trata como operador de bit'. También creí en esto, hasta que vi esta referencia, https://msdn.microsoft.com/en-us/library/kxszd0kx.aspx – user3207158

2

OrElse evalúa la primera expresión y luego si es verdadera procederá a la declaración mientras OR evalúa dos expresiones antes de que se proceda a su declaración

Ejemplo:.

Textbox1.Text= 4 

Textbox2.Text= "" 

Usando OrElse

If TextBox1.Text > 2 OrElse TextBox2.Text > 3 Then 
     MsgBox("True") 
    End If 

El resultado es: VERDADERO


Usar o

If TextBox1.Text > 2 Or TextBox2.Text > 3 Then 

      MsgBox("True") 
    End If 

El resultado es: error no puede convertir cadena a duplicar.

Cuestiones relacionadas