Question

En C# (et n'hésitez pas à répondre pour d'autres langages), dans quel ordre le runtime évalue-t-il une instruction logique ?

Exemple:

DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
    //do some stuff with myDt
}

Quelle instruction le runtime évalue-t-il en premier -

myDt != null

ou:

myDt.Rows.Count > 0

?

Y a-t-il un moment où le compilateur évaluerait l’instruction à l’envers ?Peut-être lorsqu'un opérateur « OU » est impliqué ?


& est connu comme un opérateur logique au niveau du bit et évaluera toujours toutes les sous-expressions

Quel est un bon exemple d'utilisation de l'opérateur au niveau du bit au lieu du « booléen court-circuité » ?

Était-ce utile?

La solution

C# :De gauche à droite, et le traitement s'arrête si une non-correspondance (évaluée à faux) est trouvée.

Autres conseils

" C# :De gauche à droite, et le traitement s'arrête si une correspondance (évaluée comme vraie) est trouvée."

Le mouton zombie a tort, pas assez de représentants pour voter contre.

La question concerne l'opérateur &&, pas le || opérateur.

Dans le cas de &&, l'évaluation s'arrêtera si un FALSE est trouvé.

Dans le cas de || L'évaluation s'arrête si un vrai est trouvé.

Je me rends compte que cette question a déjà reçu une réponse, mais j'aimerais ajouter une autre information liée au sujet.

Dans les langues, comme C ++, où vous pouvez réellement surcharger le comportement des && et || opérateurs, il est fortement recommandé que vous Ne faites pas cela.En effet, lorsque vous surchargez ce comportement, vous finissez par forcer l'évaluation des deux côtés de l'opération.Cela fait deux choses :

  1. Cela rompt le mécanisme d'évaluation paresseuse car la surcharge est une fonction qui doit être invoquée, et donc les deux paramètres sont évalués avant d'appeler la fonction.
  2. L'ordre d'évaluation desdits paramètres n'est pas garanti et peut être spécifique au compilateur.Par conséquent, les objets ne se comporteraient pas de la même manière que dans les exemples répertoriés dans la question/réponses précédentes.

Pour plus d'informations, lisez le livre de Scott Meyers, C++ plus efficace.Acclamations!

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. L'évaluation se fait de gauche à droite
  2. Et aussi l'opérateur s'assure que seulement si le côté gauche était VRAI, le côté droit sera évalué (très important, puisque ifx n'est rien, x.go plantera)

Vous pouvez utiliser Et au lieu deEtAussi en vb.auquel cas le côté gauche est également évalué en premier, mais le côté droit sera évalué quel que soit le résultat.

Meilleur entrainement:Utilisez toujours AndAlso, sauf si vous avez une très bonne raison de ne pas le faire.


Il a été demandé dans un suivi pourquoi ou quand quelqu'un utiliserait-il And au lieu de AndAlso (ou & au lieu de &&) :Voici un exemple:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

Dans ce cas, je souhaite initialiser X et Y.Y doit être initialisé pour que y.DoDance puisse s'exécuter.Cependant, dans la fonction init(), je fais également quelque chose de plus, comme vérifier qu'un socket est ouvert, et seulement si cela fonctionne bien, par exemple. les deux, je devrais aller de l'avant et faire le x.process(y).

Encore une fois, ce n'est probablement pas nécessaire ni élégant dans 99% des cas, c'est pourquoi j'ai dit que la valeur par défaut devrait être d'utiliser Et aussi.

@shsteimer

Le concept auquel fait référence la modestie est la surcharge des opérateurs.dans la déclaration :...A est évalué en premier, s’il est évalué à faux, B n’est jamais évalué.de même pour

Il ne s'agit pas d'une surcharge des opérateurs.La surcharge d'opérateurs est le terme utilisé pour vous permettre de définir un comportement personnalisé pour les opérateurs, tels que *, +, =, etc.

Cela vous permettrait d'écrire votre propre classe 'Log', puis de le faire

a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.

Ce faisant

a() || b() // be never runs if a is true

s'appelle en fait Évaluation des courts-circuits

ZombieSheep est à mort.Le seul « piège » qui pourrait attendre est que cela n’est vrai que si vous utilisez l’opérateur &&.Lors de l'utilisation de l'opérateur &, les deux expressions seront évaluées à chaque fois, que l'une ou les deux soient évaluées comme fausses.

if (amHungry & whiteCastleIsNearby)
{
   // The code will check if White Castle is nearby
   // even when I am not hungry
}

if (amHungry && whiteCastleIsNearby)
{
   // The code will only check if White Castle is nearby
   // when I am hungry
}

Notez qu'il existe une différence entre && et & concernant la quantité de votre expression évaluée.

&& est connu comme un ET booléen court-circuité et, comme l'ont noté d'autres ici, s'arrêtera tôt si le résultat peut être déterminé avant que toutes les sous-expressions ne soient évaluées.

& est connu comme un opérateur logique au niveau du bit et évaluera toujours toutes les sous-expressions.

En tant que tel:

if (a() && b())

J'appellerai seulement b si un Retour vrai.

cependant ceci :

if (a() & b())

J'appellerai toujours les deux un et b, même si le résultat de l'appel un est faux et donc connu pour être FAUX quel que soit le résultat de l'appel b.

Cette même différence existe pour le || et | les opérateurs.

Certaines langues présentent des situations intéressantes où les expressions sont exécutées dans un ordre différent.Je pense spécifiquement à Ruby, mais je suis sûr qu'ils l'ont emprunté ailleurs (probablement Perl).

Les expressions dans la logique resteront de gauche à droite, mais par exemple :

puts message unless message.nil?

Ce qui précède évaluera "Message.nil?" Tout d'abord, alors s'il évalue False (sauf si c'est comme si sauf il s'exécute lorsque la condition est fausse au lieu de vrai), "met le message" sera exécuté, qui imprime le contenu de la variable de message à l'écran.

C'est parfois une façon intéressante de structurer votre code...Personnellement, j'aime l'utiliser pour des doublures très courtes comme celles ci-dessus.

Modifier:

Pour que ce soit un peu plus clair, ce qui précède est le même que :

unless message.nil?
  puts message
end

Celui de gauche, s'arrête alors s'il est nul.

Modifier:Dans vb.net, il évaluera les deux et générera éventuellement une erreur, sauf si vous utilisez AndAlso

Le concept auquel fait référence la modestie est la surcharge des opérateurs.dans la déclaration :

if( A && B){
    // do something
}

A est évalué en premier, s’il est évalué à faux, B n’est jamais évalué.de même pour

if(A || B){
    //do something
}

A est évalué en premier, s'il est évalué à vrai, B n'est jamais évalué.

Ce concept de surcharge s'applique (je pense) à tous les langages de style C, et à bien d'autres également.

Non, au moins le compilateur C# ne fonctionne pas à l'envers (dans && ou ||).C'est de gauche à droite.

Lorsque les éléments sont tous alignés, ils sont exécutés de gauche à droite.

Lorsque les éléments sont imbriqués, ils sont exécutés de l’intérieur vers l’extérieur.Cela peut sembler déroutant, car généralement ce qui est « le plus intérieur » se trouve sur le côté droit de la ligne, il semble donc que cela va à l'envers...

Par exemple

a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );

Les choses se passent comme ceci :

  • Appel GetAddress avec le littéral "Orion"
  • Appel GetSummary avec le littéral "Orion" et le résultat de GetAddress
  • Appel Foo avec le littéral 5 et le résultat de GetSummary
  • Attribuez cette valeur à a

J'aime les réponses d'Orion.J'ajouterai deux choses :

  1. Le sens de gauche à droite s'applique toujours en premier
  2. L'interne vers l'extérieur pour garantir que tous les arguments sont résolus avant d'appeler la fonction

Disons que nous avons l'exemple suivant :

a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
           GetSummary("Chris", GetAddress("Chris")));

Voici l'ordre d'exécution :

  1. GetAddress("Orion")
  2. GetSummary("Orion", ...)
  3. GetAddress("Chris")
  4. GetSummary("Chris", ...)
  5. Foo(...)
  6. Attribue à a

Je ne peux pas parler des exigences légales de C# (même si j'ai testé un exemple similaire en utilisant Mono avant d'écrire cet article), mais cet ordre est garanti en Java.

Et juste pour être complet (puisqu'il s'agit également d'un fil indépendant du langage), il existe des langages comme C et C++, où l'ordre n'est pas garanti à moins qu'il n'y ait un point de séquence.Les références: 1, 2.Cependant, en répondant à la question du fil, && et || sont des points de séquence en C++ (sauf surcharge ;voir aussi l'excellente réponse d'OJ).Alors quelques exemples :

  • foo() && bar()
  • foo() & bar()

Dans le && cas, foo() est garanti de fonctionner avant bar() (si ce dernier est exécuté), puisque && est un point de séquence.Dans le & Dans ce cas, aucune garantie de ce type n'est donnée (en C et C++), et en effet bar() peut courir avant foo(), ou vice versa.

Quel est un bon exemple d'utilisation de l'opérateur au niveau du bit au lieu du « booléen court-circuité » ?

Supposons que vous ayez des indicateurs, par exemple pour les attributs de fichier.Supposons que vous ayez défini READ sur 4, WRITE sur 2 et EXEC sur 1.En binaire, cela donne :

READ  0100  
WRITE 0010  
EXEC  0001

Chaque indicateur a un bit défini et chacun est unique.Les opérateurs au niveau du bit vous permettent de combiner ces indicateurs :

flags = READ & EXEC; // value of flags is 0101

J'ai entendu quelque part que les compilateurs fonctionnent à l'envers, mais je ne suis pas sûr que cela soit vrai.

Vous utilisez & lorsque vous souhaitez spécifiquement évaluer toutes les sous-expressions, probablement parce qu'elles ont les effets secondaires souhaités, même si le résultat final sera FAUX et ainsi ne pas exécuter votre alors une partie de votre si-déclaration.

Notez que & et | fonctionne pour les masques bitwise et les valeurs booléennes et n'est pas seulement pour les opérations bitIls sont appelé au niveau du bit, mais ils sont définis à la fois pour les types de données entiers et booléens en C#.

@csmba:

Il a été demandé dans un suivi pourquoi ou quand quelqu'un utiliserait-il And au lieu de AndAlso (ou & au lieu de &&) :Voici un exemple:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

Dans ce cas, je souhaite initialiser X et Y.Y doit être initialisé pour que y.DoDance puisse s'exécuter.Cependant, dans la fonction init(), je fais également quelque chose de plus, comme vérifier qu'un socket est ouvert, et seulement si cela fonctionne bien, pour les deux, je devrais continuer et faire le x.process(y).

Je pense que c'est plutôt déroutant.Bien que votre exemple fonctionne, ce n'est pas le cas typique d'utilisation And (et j'écrirais probablement ceci différemment pour que ce soit plus clair). And (& dans la plupart des autres langages) est en fait l'opération bitwise-and.Vous l'utiliseriez pour calculer des opérations sur les bits, par exemple pour supprimer un bit d'indicateur ou pour masquer et tester des indicateurs :

Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
    MsgBox("The text will be set in italic.")
End If

Le langage de programmation D fait l'affaire évaluation de gauche à droite avec court-circuit et n'a pas permettre une surcharge du && et '||' les opérateurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top