web-dev-qa-db-fra.com

(OrElse et Or) et (AndAlso et And) - Quand utiliser?

Quelle est la différence entre (OrElse et Or) et (AndAlso et And)? Y a-t-il une différence dans leurs performances, disons le bénéfice de la correction ?? Y a-t-il une situation où je ne devrais pas utiliser OrElse et AndAlso?

44
aer

Or/And évaluera toujours les deux 1 les expressions, puis renvoyer un résultat. Ils ne sont pas pas court-circuités.

OrElse/AndAlso sont court-circuitage . L'expression droite n'est évaluée que si le résultat ne peut être déterminé à partir de l'évaluation de l'expression gauche seule. (Cela signifie: OrElse n'évaluera l'expression droite que si l'expression gauche est fausse et AndAlso n'évaluera l'expression droite que si l'expression gauche est vraie.)

En supposant que aucun effet secondaire ne se produit dans les expressions et que les expressions ne sont pas dépendantes (et toute surcharge d'exécution est ignorée), alors ce sont les mêmes.

Cependant, dans de nombreux cas, c'est que les expressions dépendent . Par exemple, nous voulons faire quelque chose quand une liste n'est pas rien et a plus d'un élément:

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

Cela peut également être utilisé pour éviter un calcul "coûteux" (ou des effets secondaires, ick!):

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

Personnellement, je trouve que AndAlso et OrElse sont les opérateurs corrects à utiliser dans tous sauf le 1% - ou moins, espérons-le! - des cas où un effet secondaire est souhaité.

Codage heureux.


1 Une exception levée dans la première expression empêchera la deuxième expression d'être évaluée, mais cela ne devrait pas être surprenant.

67
user166390

Outre le court-circuitage mentionné dans les autres réponses, Or/And sont utilisables comme opérateurs au niveau du bit où OrElse/AndAlso ne le sont pas. Les opérations au niveau du bit incluent la combinaison de valeurs d'énumérations Flags, telles que l'énumération FileAttributes où vous pouvez indiquer qu'un fichier est à la fois en lecture seule et masqué par FileAttributes.ReadOnly Or FileAttributes.Hidden

10
Gideon Engelberth

La différence est que OrElse et AndAlso court-circuiteront en fonction de la première condition, ce qui signifie que si la première condition ne passe pas, la deuxième (ou plusieurs) conditions ne sera pas évaluée. Ceci est particulièrement utile lorsque l'une des conditions peut être plus intensive que l'autre.

Exemple où Or va bien (les deux conditions sont évaluées):

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

Peu importe dans quel sens ils sont évalués

Le AndAlso suivant est utile car la deuxième condition peut échouer

If Not SomeObject Is Nothing AndAlso CheckObjectExistsInDatabase(SomeObject) Then

Cela permet à la première condition de vérifier si l'objet a été défini et seulement s'il a été défini ira vérifier la base de données (ou une autre tâche). S'il s'agissait d'un simple mot clé And, les deux seraient évalués.

4
davidsleeps

@Gideon - heureux que quelqu'un l'ait signalé. Voici un test simple qui montre l'impact dramatique d'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
2
dbasnett