Jaka jest różnica między or i OrElse ?
if temp is dbnull.value or temp = 0
powoduje błąd:
Operator „=” nie jest zdefiniowany dla typu „DBNull” i typu „Integer”.
podczas gdy ten działa jak urok !?
if temp is dbnull.value OrElse temp = 0
Odpowiedzi:
OrElse
jest operatorem zwarcia , Or
nie jest.
Zgodnie z definicją operatora logicznego „or”, jeśli pierwszy człon jest True, to całość jest zdecydowanie prawdziwa - więc nie musimy oceniać drugiego członu.
OrElse
wie o tym, więc nie próbuje tego oceniać, temp = 0
kiedy już to ustaliłtemp Is DBNull.Value
Or
nie wie o tym i zawsze będzie próbował ocenić oba terminy. Kiedy temp Is DBNull.Value
nie można go porównać do zera, więc się przewraca.
Powinieneś użyć ... cóż, cokolwiek ma sens.
Jest to takie samo zachowanie, jak w przypadku C #, gdzie wszyscy używają Coditional Or (||) i Conditional And (&&), gdzie masz również normalne Or (|) i normalne And (&). Porównanie C # z VB.Net to:
| => Lub
|| => OrElse
& => I
&& => I także
Condifitonal boolowskie operatory są bardzo przydatne w zapobieganiu zagnieżdżaniu konstrukcji if. Ale czasami potrzebne są normalne operatory boolowskie, aby zapewnić trafienie w obie ścieżki kodu.
|
i &
są operatorami bitowymi w C #, a nie operacjami logicznymi.
OrElse jest zwarte , co oznacza, że tylko jedna strona wyrażenia zostanie przetestowana, jeśli pierwsza strona jest zgodna.
Podobnie jak AndAlso przetestuje tylko jedną stronę wyrażenia, jeśli pierwsza połowa zakończy się niepowodzeniem.
(Spojrzałem na inne odpowiedzi i zdałem sobie sprawę, że bardzo się myliłem)
Operator OrElse "wykonuje skracającą logiczną dysjunkcję na dwóch wyrażeniach", to znaczy: jeśli lewy operand jest prawdziwy, a więc całe wyrażenie jest gwarantowane, prawy operand nie będzie nawet oceniany (jest to przydatne w przypadki takie jak:
string a;
//...
if (a is null) or (a = "Hi") //...
aby uniknąć rzutu NullReferenceException przez operand po prawej stronie.
Jestem szczerze zdumiony, że ta ( leniwa ocena ) nie jest domyślnym zachowaniem or
i and
tak jak jest w C / C ++ i C # (i wielu innych językach ...)
OrElse ocenia pierwsze wyrażenie, a następnie, jeśli jest prawdziwe, przejdzie do instrukcji, podczas gdy OR ocenia dwa wyrażenia, zanim przejdzie do ich instrukcji.
Przykład:
Textbox1.Text= 4
Textbox2.Text= ""
Korzystanie z OrElse
If TextBox1.Text > 2 OrElse TextBox2.Text > 3 Then
MsgBox("True")
End If
Wynik to: PRAWDA
Korzystanie z OR
If TextBox1.Text > 2 Or TextBox2.Text > 3 Then
MsgBox("True")
End If
Wynik: błąd nie może przekonwertować ciągu na podwójny.
Odpowiedź Berta nie jest zbyt dokładna. „|” lub „&” jest operatorem logicznym, w C # zawsze traktuje go jako operator bitowy, zobacz poniższy kod jako przykład
static void Main()
{
object a = null;
int b = 3;
if (a == null | a.ToString() == "sdffd")
{
Console.WriteLine("dddd");
}
Console.WriteLine(b | b);
Console.Read();
}
Poniżej znajduje się 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
kiedy używasz || aby przetestować "a == null" i "a.ToString () ==" sdffd ", IL będzie
.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
Teraz widzisz różnicę, proszę nie myśl '|' lub „and” jako operator warunkowy, to tylko operator logiczny, nie sądzę, aby było konieczne używanie go do oceny stanu
The '|' or '&' is logical operator, in C #, it always treat as bit operator
. W to też wierzyłem, dopóki nie zobaczyłem tego odniesienia, msdn.microsoft.com/en-us/library/kxszd0kx.aspx
O ile logika twojego kodu nie wymaga zachowania zwarciowego zapewnianego przez OrElse, skłaniałbym się do użycia operatora Or, ponieważ:
Przyczyną niepowodzenia kompilacji w tym przykładzie jest kolejność operacji.
Parser wyrażeń próbuje najpierw ocenić „dbnull.value lub temp”.
if temp is (dbnull.value or temp) = 0
Błąd występuje tutaj, ponieważ nie można wykonać bitowego OR między liczbą całkowitą (temp) a wartością dbnull.value.
OrElse rozwiązuje ten problem, nie dlatego, że jest zwarty, ale dlatego, że jest niższy w kolejności operacji , więc najpierw są oceniane „temp is dbnull.value” i „3 = 0”, a nie parser próbuje porównać dbNull i temp.
Więc ocena z OrElse działa tak, jak się spodziewasz: (zakładając temp = 3)
if temp is dbnull.value OrElse temp = 0 then
if 3 is dbnull.value OrElse 3 = 0 then
if false OrElse 3=0 then
if false OrElse false then
if false then
To był egzamin wstępny w firmie programistycznej, dla której pracowałem, i był to częsty problem, z którym miałem do czynienia w VB6. Dlatego dobrym pomysłem jest umieszczanie wyrażeń podrzędnych w nawiasach, gdy używasz operatorów boolowskich:
Skompilowałoby się to poprawnie:
if (temp is dbnull.value) Or (temp = 0) then
Chociaż, jak wszyscy już zauważyli, OrElse i AndAlso są naprawdę właściwymi operatorami do użycia w tym kontekście.