(OrElse и Or) и (AndAlso и And) - Когда использовать?

В чем разница между (OrElse и Or) и (AndAlso и And)? Есть ли какая-то разница в их выступлениях, скажем, в пользу правильности?? Есть ли ситуации, в которых я не должен использовать OrElse и AndAlso?

4 ответа

Решение

Or/And всегда будет вычислять оба выражения и затем возвращать результат. Они не закорочены.

OrElse/AndAlso являются короткими замыканиями. Правое выражение оценивается, только если результат не может быть определен на основе оценки только левого выражения. (Это означает: OrElse будет вычислять только правое выражение, если левое выражение ложно, и AndAlso оценит только правильное выражение, если левое выражение истинно.)

Если предположить, что в выражениях не возникает побочных эффектов и выражения не являются зависимыми (и любые накладные расходы на выполнение игнорируются), то они одинаковы.

Однако во многих случаях это то, что выражения являются зависимыми. Например, мы хотим сделать что-то, когда List не является Nothing и имеет более одного элемента:

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

Это также можно использовать, чтобы избежать "дорогих" вычислений (или побочных эффектов, ick!):

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

Лично я считаю, что AndAlso а также OrElse правильные операторы для использования во всех, кроме 1% - или меньше, надеюсь! - случаев, когда побочный эффект желателен.

Удачного кодирования.


1 Исключение, выданное в первом выражении, предотвратит оценку второго выражения, но это вряд ли должно удивлять.

Помимо короткого замыкания, упомянутого в других ответах, Or / And могут использоваться как побитовые операторы, где OrElse / AndAlso не. Побитовые операции включают объединение значений перечислений Flags, таких как перечисление FileAttributes, где вы можете указать, что файл доступен только для чтения и скрыт FileAttributes.ReadOnly Or FileAttributes.Hidden

Разница в том, что OrElse и AndAlso будут закорачиваться на основе первого условия, что означает, что если первое условие не пройдет, второе (или более) условие не будет оцениваться. Это особенно полезно, когда одно из условий может быть более интенсивным, чем другое.

Пример где Or хорошо (оба условия оценены):

If Name = "Fred" Or Name = "Sam" Then

Это действительно не имеет значения, каким образом они оцениваются

Следующие AndAlso полезно, потому что второе условие может потерпеть неудачу

If Not SomeObject Is Nothing AndAlso CheckObjectExistsInDatabase(SomeObject) Then

Это позволяет при первом условии проверить, был ли установлен объект, и только если он был установлен, пойдет и проверит базу данных (или какую-либо другую задачу). Если бы это было просто And ключевое слово, оба будут оценены.

@ Гидеон - рад, что кто-то указал на это. Вот простой тест, который показывает драматическое влияние 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
Другие вопросы по тегам