或者对OrElse

时间:2009-07-23 09:58:27

标签: vb.net

OrElse 之间的区别是什么?

if temp is dbnull.value or temp = 0

产生错误:

  

没有为类型'DBNull'定义Operator'='并输入'Integer'。

虽然这个就像魅力一样!?

if temp is dbnull.value OrElse temp = 0

8 个答案:

答案 0 :(得分:130)

OrElse短路运算符,Or不是。

通过布尔'或'运算符的定义,如果第一项是True,那么整体肯定是正确的 - 所以我们不需要评估第二项。

OrElse知道这一点,因此一旦确定temp = 0

,就不会尝试评估temp Is DBNull.Value

Or不知道这一点,并且总是会尝试评估这两个字词。当temp Is DBNull.Value时,它无法与零进行比较,因此会失败。

你应该使用......好吧,无论哪个都有意义。

答案 1 :(得分:38)

这与C#的行为相同,其中每个人都使用Coditional Or(||)和Conditional And(&&),其中你也有正常的Or(|)和正常的和(&) 。所以将C#与VB.Net进行比较是:

| =>或

|| => OrElse运算

&安培; =>和

&安培;&安培; => AndAlso

condifitonal布尔运算符非常有用,可以防止嵌套if构造。但有时需要普通的布尔运算符来确保命中两个代码路径。

答案 2 :(得分:8)

OrElse 短路,这意味着如果第一面匹配,则只会测试表达式的一侧。

就像AndAlso只测试表达式的一侧,如果前半部分是失败的话。

答案 3 :(得分:4)

(我看了其他答案并意识到我非常错误)

OrElse运算符“对两个表达式执行短路逻辑析取”,也就是说:如果左操作数为真,因此保证整个表达式为真,则不会对右操作数进行求值(这在以下情况下很有用:

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

避免右手操作数抛出NullReferenceException。

我真的很惊讶这个( lazy evaluation )不是orand的默认行为,因为它在C / C ++中C#(以及许多其他语言......)

答案 4 :(得分:4)

OrElse计算第一个表达式,然后判断它是否为真,它将继续执行语句,而OR在计算两个表达式之前将继续执行它们的语句。

示例:

@if($book->name == $file['basename'])
       <p>Book</p>
@endif

使用OrElse

Textbox1.Text= 4

Textbox2.Text= ""

结果是: TRUE

使用OR

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

结果是:错误无法将字符串转换为double。

答案 5 :(得分:3)

Bert的回答并不准确。 '|'或'&amp;'是逻辑运算符,在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

现在你可以看到差异,请不要认为'|'或'和'作为条件运算符,它只是一个逻辑运算符,我认为没有必要用它来判断条件

答案 6 :(得分:0)

除非您的代码逻辑需要OrElse提供的短路行为,否则我倾向于使用Or运算符,因为:

  • 使用“或”很简单,并且需要更少的输入。
  • 在大多数情况下,使用OrElse节省的计算时间可以忽略不计。
  • 最重要的是,使用OrElse可以在以后的子句中隐藏错误,这些子句直到程序逻辑最终满足这些条件时才可能被发现。

答案 7 :(得分:0)

示例中编译失败的原因是操作顺序。

表达式解析器尝试首先评估“ dbnull.value或temp”。

if temp is (dbnull.value or temp) = 0

错误在这里,因为您不能在整数(temp)和dbnull.value之间进行按位或运算。

OrElse解决了此问题,不是因为它短路,而是因为它在操作顺序上比,因此首先评估“ temp is dbnull.value”和“ 3 = 0” ,而不是解析器尝试比较dbNull和temp。

因此,使用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实际上是在这种情况下使用的正确运算符。