2009-10-08 10 views
9

J'ai utilisé l'esperluette unique (&) en C# pour signifier "vérifier l'instruction conditionnelle deuxième même si la première est false".Quelle est la deuxième signification d'une seule perluète en C#?

Mais ce qui suit semble être un sens différent de & tout à fait, quelqu'un peut-il expliquer comment fonctionne i & 1 dans l'exemple suivant?

List<int> scores = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 }; 
var evenScores = scores.Where(i => i % 2 == 0); 
var evenScores2 = scores.Where(i => (i & 1) == 0); 
+0

Si vous pensez à cette affirmation ... C'est inefficace. – Min

+0

Je l'ai eu de cette question http://stackoverflow.com/questions/1537528/how-to-convert-system-linq-enumerable-wherelistiteratorint-to-listint/1537568#1537568 dans lequel il a été indiqué que la variante & était plus rapide. –

Répondre

31

Un seul & est "Bitwise opérateur AND", tout comme dove m'a dit. Je regarde la deuxième partie de la question: "pourquoi ça marche?"

Pensez en binaire:

000 = 0 
001 = 1 
010 = 2 
011 = 3 
100 = 4 
101 = 5 
110 = 6 
111 = 7 
and so on 

Remarque Les numéros tous même se termine par 0; donc si le dernier bit bit vérifier contre 1 renvoie zéro (signifiant "ne correspond pas"), c'est un nombre pair;

+0

En C++, vous pouvez utiliser & avec des valeurs booléennes * car * un booléen passe automatiquement à zéro ou un (et arrière) - une fois que vous avez optimisé les distributions, vous avez quelque chose d'équivalent à && mais sans évaluation de court-circuit (donc vous garantissez que les effets secondaires de la bonne sous-expression se produisent). Je suppose que cela s'applique en C# et Java, mais ne me souviens pas à coup sûr ATM. – Steve314

+0

@Steve: Selon la question d'OP, ils savent déjà que ce comportement existe pour ne pas court-circuiter la logique booléenne. –

+0

@Jeff - mais il ne savait pas ce que l'opérateur était, donc ne savait pas pourquoi cela a fonctionné pour cela.Juste en essayant de relier les connaissances existantes à la nouvelle, en clarifiant que le comportement boolique qu'Edward connaît ne correspond pas au comportement au niveau du bit que vous avez expliqué et au comportement de casting int. – Steve314

3

Opérateur au niveau du bit AND.

16

Here:

Les & operator unaire renvoie l'adresse de son opérande (nécessite unsafe contexte).

Les nombres binaires & operators sont prédéfinis pour les types entiers et bool. Pour les types entiers, & calcule le bit logique AND de ses opérandes. Pour les opérandes booléens, & calcule le AND logique de ses opérandes; c'est-à-dire que le résultat est vrai si et seulement si ses deux opérandes sont vrais. Le & operator évalue les deux opérateurs indépendamment de la valeur de premier.

6

Pour les types booléens, ce que vous avez mentionné est comment il se comporte.

Pour les types entiers, il s'agit de l'opérateur "et" bit à bit.

Il peut être surchargé pour d'autres types.

Fondamentalement, l'expression (i & 1) == 0 vérifie si le bit le moins significatif de i est activé, ce qui se produit uniquement si le nombre est impair.

4

L'esperluette représente une opération ET au niveau du bit. Un opérateur bit retourne le résultat d'une comparaison entre chaque bit correspondant dans les deux opérandes.

Par exemple, si x est 0110 et y est 1010, alors au niveau du bit de x et y (x & y) résultats en 0010.

7

réponses précédentes ne sont pas vraies, mais ne dit pas comment & diffère de & &, que je pensais était votre question initiale, donc je vais prendre ça. Comme il a été dit, "&" est un AND bit à bit. "& &" est un AND logique.& exécute une opération ET sur ses opérandes bit par bit, et en général des fonctions exactement comme plus ou temps ou n'importe quel opérateur arithmétique. & & est plus complexe. Si compare chacun de ses opérandes contre zéro. Si le premier opérande est nul, il prend la valeur FALSE et court-circuite le reste de l'expression, c'est-à-dire qu'il n'évalue aucun opérande restant. Si la première valeur est différente de zéro, elle examine la deuxième valeur. Si c'est zéro, il prend la valeur false, sinon il prend la valeur true. Dans les deux cas, il continue à évaluer l'expression.

C'est, il y a deux différences fondamentales entre & et & &:

  1. & actionnent bit par bit alors que & & ne considère que zéro et non zéro et retourne toujours 0 ou 1. Ainsi 5 & 6 (binaire 101 & 110) donne 4 (binaire 100), tandis que 5 & & 6 donne 1 (vrai).

  2. & & "courts-circuits". Si la première valeur est zéro, elle n'évalue pas la deuxième valeur. & n'a pas cette règle. Ceci est important de plusieurs façons. Tout d'abord, si la seconde valeur a des effets secondaires, alors avec & ces effets secondaires se produisent toujours, alors qu'avec & & ils ne le font pas. Donc, "x & (y ++)" sera toujours incrémenté y, tandis que "x & & (y ++)" n'augmentera que si x n'est pas zéro. Cela devient plus important - et peut-être plus subtil - si le second opérande est un appel de fonction. Deuxièmement, la première valeur peut tester quelque chose qui détermine que la deuxième valeur est invalide. Comme "x! = NULL & & x-> foo == 3". Avec &, lorsque x est nul, il pourrait exploser avec des défauts de segment ou l'équivalent. Et troisièmement, il peut y avoir des gains de performance importants. Life, "x! = 'A' & & readTonsOfStuffFromDatabaseAndCalculateTotal (x)". Avec &, la lecture se produirait indépendamment, et peut-être une perte de temps totale.

C'est la raison pour laquelle nous utilisons presque toujours & & pour des choses qui sont vraiment des opérations logiques, et de limiter l'utilisation de & quand nous voulons vraiment une opération peu sage. Mais il y a des moments où vous ne voulez pas que le court-circuit se produise, et dans ce cas & peut être un bon choix. Mais si vous l'utilisez pour fonctionner "logiquement", soyez très prudent avec les opérandes qui peuvent avoir des valeurs autres que 0 ou 1. 1 & & 2 est vrai, mais 1 & 2 est faux.

+0

Merci pour * effectivement * l'expliquer – BritishDeveloper

+1

Notez qu'en C#, l'opérateur '&&' ne peut être utilisé que entre deux 'bool', donc demander si le premier opérande est nul n'a aucun sens (en C# un' bool' ne peut être que 'false' ou' true', jamais un nombre), et en particulier '5 && 6' n'est pas autorisé. Mais la description est pertinente pour d'autres langues. –

+0

Oups, j'ai dérivé de C# en C/C++. – Jay

Questions connexes