Answers:
OrElse
是短路运算符,Or
不是。
根据布尔“或”运算符的定义,如果第一项为True,则整个绝对为真-因此,我们无需评估第二项。
OrElse
知道这一点,所以temp = 0
一旦确定temp Is DBNull.Value
Or
不知道这一点,因此将始终尝试对这两个术语进行评估。当时temp Is DBNull.Value
,不能将其与零进行比较,因此会掉落。
您应该使用...好,无论哪一种都有意义。
这与C#的行为相同,在C#中,每个人都使用Coditional或(||)和有条件的And(&&),同时您也具有普通的Or(|)和普通的And(&)。因此,将C#与VB.Net进行比较是:
| =>或者
|| => OrElse
&=>并且
&& => AndAlso
条件布尔运算符对于防止嵌套if结构非常有用。但是有时需要使用普通的布尔运算符来确保同时到达两个代码路径。
|
并且&
是C#中的按位运算符,根本不是布尔运算。
(我查看了其他答案后意识到自己错了)
OrElse运算符“对两个表达式执行短路逻辑求和”,这就是说:如果左操作数为true,则保证整个表达式为true,甚至不对右操作数进行求值(在情况如下:
string a;
//...
if (a is null) or (a = "Hi") //...
以避免右侧操作数抛出NullReferenceException。
我真诚地惊讶,这个(懒惰的评价)不是的默认行为or
,并and
因为它是在C / C ++和C#(和许多其他语言...)
伯特的答案不是很准确。“ |” 或'&'是逻辑运算符,在C#中,它始终视为位运算符,请参见以下代码作为示例
static void Main()
{
object a = null;
int b = 3;
if (a == null | a.ToString() == "sdffd")
{
Console.WriteLine("dddd");
}
Console.WriteLine(b | b);
Console.Read();
}
以下是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
当您使用||时 测试“ a == null”和“ a.ToString()==” sdffd”,则IL将为
.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
现在您可以看到区别,请不要认为'|' 或“和”作为条件运算符,它只是一个逻辑运算符,我认为没有必要使用它来判断条件
The '|' or '&' is logical operator, in C #, it always treat as bit operator
。我也相信这一点,直到看到此参考,msdn.microsoft.com
示例中编译失败的原因是操作顺序。
表达式解析器尝试首先评估“ dbnull.value或temp”。
if temp is (dbnull.value or temp) = 0
错误在这里,因为您不能在整数(temp)和dbnull.value之间进行按位或运算。
OrElse解决了此问题,不是因为它短路,而是因为它在操作顺序上较低,因此首先要评估“ temp is dbnull.value”和“ 3 = 0”,而不是解析器尝试比较dbNull和温度
因此,使用OrElse进行评估的效果与您期望的一样:(假设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
这实际上是在我曾经工作过的一家软件公司的入学考试中,这是我以前在VB6中遇到的一个常见问题。因此,在使用布尔运算符时括号内的子表达式是一个好主意:
这样可以正确编译:
if (temp is dbnull.value) Or (temp = 0) then
尽管,正如大家已经指出的那样,OrElse和AndAlso确实是在这种情况下使用的正确运算符。