44 votes

Une explication claire et profane de la différence entre | et || en c #?

Ok, donc je l'ai lu à ce sujet un certain nombre de fois, mais je suis encore à entendre un clair, facile à comprendre (et mémorable) de façon à apprendre la différence entre:

if (x | y)

et

if (x || y)

..dans le cadre de C#. Quelqu'un peut-il svp m'aider à apprendre cette vérité fondamentale, et comment C# spécifiquement, les traite différemment (parce qu'ils semblent faire la même chose). Si la différence d'un morceau de code a entre eux est sans importance, ce qui devrait je fais défaut comme une meilleure pratique?

81voto

John Feminella Points 116878

|| est la logique ou de l'opérateur. Voir ici. Il évalue true si au moins un des opérandes est vrai. Vous ne pouvez utiliser qu'avec des opérandes booléens; c'est une erreur de l'utiliser avec des opérandes entiers.

// Example
var one = true || bar();   // result is true; bar() is never called
var two = true | bar();    // result is true; bar() is always called

| est la ou l'opérateur. Voir ici. Si elle est appliquée pour les types boolean, il évalue true si au moins un des opérandes est vrai. Si elle est appliquée à des types d'entiers, il évalue à un autre numéro. Ce nombre a chacun de ses bits mis à 1 si au moins un des opérandes est un bit correspondant est activé.

// Example
var a = 0x10;
var b = 0x01;
var c = a | b;     // 0x11 == 17
var d = a || b;    // Compile error; can't apply || to integers
var e = 0x11 == c; // True

Pour les opérandes booléens, a || b est identique à a | b, avec la seule exception que l' b n'est pas évalué si a est vrai. Pour cette raison, || il est dit "court-circuit".

Si la différence d'un morceau de code a entre eux est sans importance, ce qui devrait je fais défaut comme une meilleure pratique?

Comme indiqué, la différence n'est pas hors de propos, de sorte que cette question est en partie discutable. Comme pour une "meilleure pratique", il n'en est pas un: il vous suffit de choisir l'opérateur est correcte à utiliser. En général, les gens favorisent || sur | pour les opérandes booléens puisque vous pouvez être sûr qu'il ne produira pas inutile d'effets secondaires.

44voto

Guffa Points 308133

Lorsqu'il est utilisé avec opérandes booléens l' | de l'opérateur est un opérateur logique tout comme ||, mais la différence est que l' || opérateur ne court-circuit de l'évaluation et de l' | opérateur ne fonctionne pas.

Cela signifie que le deuxième opérande est toujours évalué à l'aide de l' | de l'opérateur, mais à l'aide de l' || de l'opérateur, le deuxième opérande n'est évaluée que si le premier opérande est false.

Le résultat de l'expression est toujours la même pour les deux operatrors, mais si l'évaluation de la deuxième opérande provoque quelque chose d'autre à changer, qui n'est garanti que si vous utilisez l' | de l'opérateur.

Exemple:

int a = 0;
int b = 0;

bool x = (a == 0 || ++b != 0);

// here b is still 0, as the "++b != 0" operand was not evaluated

bool y = (a == 0 | ++b != 0);

// here b is 1, as the "++b != 0" operand was evaluated.

Le court-circuit d'évaluation de l' || de l'opérateur peut être utilisé pour écrire moins de code, le deuxième opérande seulement est évalué si le premier opérande est vrai. Au lieu d'écrire comme ceci:

if (str == null) {
   Console.WriteLine("String has to be at least three characters.");
} else {
   if (str.Length < 3) {
      Console.WriteLine("String has to be at least three characters.");
   } else{
      Console.WriteLine(str);
   }
}

Vous pouvez écrire comme ceci:

if (str == null || str.Length < 3) {
   Console.WriteLine("String has to be at least three characters.");
} else{
   Console.WriteLine(str);
}

Le deuxième opérande n'est évaluée que si la première est fausse, alors vous savez que vous pouvez utiliser en toute sécurité la chaîne de référence dans le deuxième opérande comme il ne peut pas être null si le deuxième opérande est évaluée.

Dans la plupart des cas, vous pouvez utiliser l' || de l'opérateur plutôt que de l' | de l'opérateur. Si le premier opérande est faux, il n'est pas nécessaire d'évaluer le second opérande pour obtenir le résultat. Aussi, beaucoup de gens (évidemment) ne sait pas que vous pouvez utiliser l' | de l'opérateur avec des opérandes booléens, de sorte qu'ils deviennent confus quand il voit qu'il a utilisé de cette façon dans le code.

10voto

Cheeso Points 87022

Ils ne sont pas les mêmes. L'un est OU au niveau du bit et est un OU logique.

X || Y est un ou logique, qui signifie la même chose que "X ou Y" et s'applique aux valeurs bool. Il est utilisé dans des conditions ou des tests. X et Y dans ce cas, peut être remplacé par n'importe quelle expression qui renvoie un bool. Exemple:

if (File.Exists("List.txt")  ||  x > y )  { ..}

La clause évalue à true si l'une des deux conditions est vraie. Si la première condition est vraie (si le fichier existe), alors que la deuxième condition ne doivent pas et ne sera pas évaluée.

La seule pipe ( | ) est un bit à bit OU. Pour savoir ce que cela signifie que vous devez être de comprendre comment les nombres sont stockés dans l'ordinateur. Supposons que vous avez un 16 bits (Int16) qui contient la valeur 15. C'est stockée comme 0x000F (en hexadécimal) qui est le même que 0000 0000 0000 1111 en binaire. Le bit à bit OU prend deux quantités et de la OU de chaque paire de bits correspondants, de sorte que si le bit est à 1 dans le plan de la quantité, il est de 1 dans le résultat. Par conséquent, si a = 0101 0101 0101 0101 (qui évalue à 0x5555 en hexadécimal) et b = 1010 1010 1010 1010 (qui est 0xaaaaa), alors a | b = 1111 1111 1111 1111 = 0xFFFF.

Vous pouvez utiliser au niveau du bit OU du (seul tuyau) en C# pour tester si un ou plus d'un ensemble particulier de bits est activé. Vous pouvez le faire si vous avez, disons, 12 des booléens ou des valeurs binaires de test, et ils sont tous indépendants. Supposons que vous disposez d'un élève de la base de données. Un ensemble indépendant de booléens peuvent être, par exemple, mâle/femelle, domicile/sur le campus, courant/non-courant, inscrits/non inscrits, etc. Plutôt que de stocker un champ booléen pour chacune de ces valeurs, vous pouvez stocker un seul bit pour chacun. Le mâle/femelle pourrait être bits 1. inscrits/non peut-être 2 bits.

Ensuite, vous pouvez utiliser

 if ((bitfield | 0x0001) == 0x0001) { ... }

comme un test pour voir si aucun bit n'est activée, à l'exception de "l'élève est un garçon de bits, ce qui est ignoré. Hein? Ainsi, le bit à bit OU retourne 1 pour chaque bit qui est en soit le nombre. Si le résultat de la bit-à-bit OU supérieur = 0x0001, qu'il n'y a pas de bits activé dans le champ de bits, sauf peut-être le premier bit (0x0001), mais vous ne pouvez pas dire à coup sûr si le premier bit est sur, car il est masqué.

Il y a un correspondant && et &, ce qui est logique ET et bit à bit ET. Ils ont de l'analogie de comportement.

Vous pouvez utiliser

 if ((bitfield &  0x0001) == 0x0001) { ... }

pour voir si le premier bit est activé dans un champ de bits.

EDIT: je ne peux pas croire que j'ai voté pour la!

5voto

Tony the Pony Points 13235

Bonne réponse, mais permettez-moi d'ajouter que les expressions du côté droit pour || ne sont pas évaluées si l'expression du côté gauche est true . Gardez cela à l'esprit pour les cas où les termes d'évaluation sont a) intensifs en performance ou b) produisent des effets secondaires (rares).

5voto

jalf Points 142628

Contrairement à ce que la plupart des réponses jusqu'à présent dire, le sens n'est pas exactement la même qu'en C++.

Pour toutes les deux expressions A et B de l'évaluation pour les booléens, A || B et A | B faire presque la même chose.

A | B évalue à la fois A et B, et si l'un d'eux prend la valeur true, le résultat est vrai.

A || B est presque la même chose, sauf qu'il évalue d'abord, puis seulement évalue B, si elle est nécessaire. Depuis l'expression entière est vrai si A ou B est vrai, B n'a pas besoin d'être testées si A est vrai. Donc || court-circuits, et saute de l'évaluation de la deuxième opérande lorsque cela est possible, où l'opérateur | toujours d'évaluer à la fois.

L'opérateur | n'est pas souvent utilisé, et souvent il ne fera pas une différence. Le seul cas que je peux penser de l'endroit où il ferait une différence, c'est ceci:

if ( foo != null || foo.DoStuff()){ // assuming DoStuff() returns a bool

}

Cela fonctionne parce que les DoStuff() membre de la fonction n'est jamais appelée que si le test échoue gauche. C'est, si toto est nulle, nous ne les appelons pas DoStuff sur elle. (ce qui nous donnerait une NullReferenceException).

Si nous avions utilisé l'opérateur|, DoStuff() sera appelée, indépendamment de savoir si toto a la valeur null ou pas.

Sur des entiers, seul l'opérateur | est défini, et est un or, comme les autres réponses décrire. L'opérateur || n'est pas définies pour les types integer, donc il est difficile de les confondre en C#.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X