OrElse和Or以及AndAlso和And - 何时使用?

47

OrElse和Or以及AndAlso和And之间有什么区别?它们的性能有什么不同,比如说正确性方面的好处?是否存在任何我不应该使用OrElse和AndAlso的情况?


2
可能是重复的问题:我应该总是使用AndAlso和OrElse运算符吗? - Brian Gideon
刚开始使用VB.NET(多年来第一次使用VB)。我上线只是为了问这个具体的问题。感谢@aer和许多人用他们伟大的答案澄清了我的疑惑。 - Hardryv
4个回答

73

或/和将始终评估两个1表达式,然后返回结果。它们不会短路。

OrElse/AndAlso短路运算符。如果仅通过左侧表达式的评估无法确定结果,则仅评估右侧表达式。(这意味着:OrElse仅在左侧表达式为false时评估右侧表达式,AndAlso仅在左侧表达式为true时评估右侧表达式。)

假设表达式中没有副作用并且表达式不依赖于(忽略任何执行开销),则它们相同。

但在许多情况下,表达式相关的。例如,我们希望在列表不为空且具有多个元素时执行某些操作:

If list IsNot Nothing AndAlso list.Length > 0 Then .. 'list has stuff

这也可以用来避免“昂贵”的计算(或副作用,呃!):

If Not Validate(x) OrElse Not ExpensiveValidate(x) Then .. 'not valid

就我个人而言,我认为AndAlsoOrElse是在除了1%或更少的情况下(希望如此!)使用的正确运算符,因为这些情况中需要副作用。

编码愉快。


1 第一个表达式中抛出的异常将阻止对第二个表达式的评估,但这应该并不令人惊讶。


10
除了其他答案中提到的短路,Or/And可用作位运算符,而OrElse/AndAlso则不行。 位运算包括组合 Flags 枚举值,例如FileAttributes枚举中,您可能使用FileAttributes.ReadOnly Or FileAttributes.Hidden表示文件既是只读又是隐藏的。

4
区别在于OrElse和AndAlso会基于第一个条件进行短路,这意味着如果第一个条件不满足,则不会评估第二个(或更多)条件。当其中一个条件可能比另一个条件更加复杂时,这特别有用。 Or适用的示例(两个条件都被评估):
If Name = "Fred" Or Name = "Sam" Then

无论如何进行评估都没有关系

AndAlso非常有用,因为第二个条件有可能失败

If Not SomeObject Is Nothing AndAlso CheckObjectExistsInDatabase(SomeObject) Then

这样可以先检查对象是否已设置,只有在设置后才会去检查数据库(或其他任务)。如果这是一个普通的And关键字,两者都会被评估。


2

@Gideon - 很高兴有人指出这一点。以下是一个简单的测试,展示了AndAlso的显著影响:

    Dim tm As New Stopwatch
    Const tries As Integer = 123456
    Dim z As Integer = 0
    Dim s() As String = New String() {"0", "one"}

    Debug.WriteLine("AndAlso")
    For x As Integer = 0 To s.Length - 1
        z = 0
        tm.Restart() 'restart the stopwatch
        For y As Integer = 0 To tries
            If s(x) = x.ToString AndAlso s(x) = y.ToString Then '<<<<<<<<<<
                z += 1
            End If
        Next
        tm.Stop()
        Debug.WriteLine(x.ToString.PadRight(3, " "c) & z.ToString.PadRight(10, " "c) & tm.Elapsed.ToString)
    Next

    Debug.WriteLine("And")
    For x As Integer = 0 To s.Length - 1
        z = 0
        tm.Restart() 'restart the stopwatch
        For y As Integer = 0 To tries
            If s(x) = x.ToString And s(x) = y.ToString Then '<<<<<<<<<<
                z += 1
            End If
        Next
        tm.Stop()
        Debug.WriteLine(x.ToString.PadRight(3, " "c) & z.ToString.PadRight(10, " "c) & tm.Elapsed.ToString)
    Next

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接