或与OrElse


94

什么之间的区别还是OrElse运算

if temp is dbnull.value or temp = 0

产生错误:

没有为类型“ DBNull”和类型“ Integer”定义运算符“ =”。

而这就像一个魅力!?

if temp is dbnull.value OrElse temp = 0

Answers:


144

OrElse短路运算符,Or不是。

根据布尔“或”运算符的定义,如果第一项为True,则整个绝对为真-因此,我们无需评估第二项。

OrElse知道这一点,所以temp = 0一旦确定temp Is DBNull.Value

Or不知道这一点,因此将始终尝试对这两个术语进行评估。当时temp Is DBNull.Value,不能将其与零进行比较,因此会掉落。

您应该使用...好,无论哪一种都有意义。


2
那么,或者仅在我的代码所依赖的具有副作用的函数调用之后才有意义吗?
拉尔夫·R·里肯巴赫

4
或在所有情况下都有意义(如果第一个项目为true,则第二个项目不触发错误)
敬畏

4
@ malach:我想是这样(在大多数其他语言中,您实际上都将OrElse行为作为默认设置):在复合条件中调用具有副作用的函数不是一个好主意,这会使代码不可读。
Utaal

4
// @敬畏:是的,但是为什么您还要浪费时间评估某些东西,而这些东西在定义上不会改变表达式的结果呢?
乌塔尔

3
@MarkJ:我真的不认为多余的四个字符会破坏可读性。另一方面,使用依赖于副作用(如malach所写)的存在的运算符才有意义,这听起来像是一个坏主意(并且可能使可读性更强!)。我认为这些地方的副作用是很大的禁忌,也无法想到我更喜欢“ Or”而不是“ OrElse”的任何情况。可惜的是这些运算符是这样工作的,因为即使使用“ Or”(尤其是来自其他语言时),“ OrElse”行为也可能是大多数人期望的。
贾尔坦(Kjartan)2012年

42

这与C#的行为相同,在C#中,每个人都使用Coditional或(||)和有条件的And(&&),同时您也具有普通的Or(|)和普通的And(&)。因此,将C#与VB.Net进行比较是:

| =>或者

|| => OrElse

&=>并且

&& => AndAlso

条件布尔运算符对于防止嵌套if结构非常有用。但是有时需要使用普通的布尔运算符来确保同时到达两个代码路径。


9
我从未真正知道这可用。感谢您提供新信息。很高兴知道,即使我真的看不到要使用“ |”的任何情况。我认为这将需要第二种条件才能使副作用产生任何意义,而我认为这本身就毫无意义!;)
Kjartan 2012年

7
据我所知,|并且&是C#中的按位运算符,根本不是布尔运算。
Nyerguds

8

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

就像AndAlso仅在前半部分失败时才测试表达式的一侧。


4

(我查看了其他答案后意识到自己错了)

OrElse运算符“对两个表达式执行短路逻辑求和”,这就是说:如果左操作数为true,则保证整个表达式为true,甚至不对右操作数进行求值(在情况如下:

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

以避免右侧操作数抛出NullReferenceException。

我真诚地惊讶,这个(懒惰的评价)不是的默认行为or,并and因为它是在C / C ++和C#(和许多其他语言...)


7
关键是,在VB经典中,只有 And和Or,它们是非短路的。我我说的很对,VB.NET的第一个beta实际上改变了这些运算符的行为-引起轩然大波,所以他们又变了,并引入了AndAlso和OrElse(短路)。我只能想象,如果这些是最好的,那么他们必须考虑的替代名称...
AakashM

1
通过提供Or和OrElse(C#中的|和||),开发人员可以选择如何处理自己的代码。使用上面的代码,我必须使用try catch来处理变量a中的空值。OrElse允许开发人员在if语句的else中将此作为已知的可能结果而不是异常进行处理。如果变量a是方法中的参数,则这种情况更加明显,在这种情况下,您对变量何时分配值的控制较少(即方法之外)
Kevin Hogg 2012年

短路也不是c#中OR和AND的默认行为。C#具有两个不同的运算符,用于按位运算和逻辑/短路运算。&&和|| 执行逻辑比较,并返回布尔值&和| 运算符是按位的,并返回一个整数值。所以1 || 2返回“ true”,1 | 2返回“ 3”。
TomXP411

4

OrElse评估第一个表达式,如果其为true,则将继续执行该语句,而OR则对两个表达式进行评估,然后再继续执行其表达式。

例:

Textbox1.Text= 4

Textbox2.Text= ""

使用OrElse

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

结果是: TRUE


使用或

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

            MsgBox("True")
  End If

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


3

伯特的答案不是很准确。“ |” 或'&'是逻辑运算符,在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

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


2
The '|' or '&' is logical operator, in C #, it always treat as bit operator。我也相信这一点,直到看到此参考,msdn.microsoft.com
en

您的答案与上下文无关。这个问题与C#无关,而与VB有关,其中的四个逻辑运算符:And,AndAlso,Or,OrElse,Not和Xor都是逻辑运算符和逐位运算符。
让·弗朗索瓦·

0

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

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

0

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

表达式解析器尝试首先评估“ 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确实是在这种情况下使用的正确运算符。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.