Warum ist &&
vorzuziehen &
und ||
vorzuziehen |
?
Ich habe jemanden gefragt, der seit Jahren programmiert, und seine Erklärung war:
Zum Beispiel in if (bool1 && bool2 && bool3) { /*DoSomething*/ }
, bool1
muss dafür Test wahr sein , bool2
die , bevor sie zu wahr zu sein hat bool3
, etc. Wenn ich einen einzelnen benutzt hatte , &
anstatt es auf die Probe keine Ordnung ist , auch wenn sie alle müssen richtig sein zu Fahren Sie mit der nächsten Zeile fort. Warum ist das überhaupt wichtig?
Hinweis: Ich möchte darauf hinweisen, dass ich das Programmieräquivalent eines Kleinkindes bin und dies keine ernsthafte oder dringende Frage ist. Es geht eher darum zu verstehen, warum Dinge auf eine bestimmte Art und Weise getan werden sollten, im Gegensatz zu einer anderen.
x & y
undx && y
werden immer zum gleichen Ergebnis ausgewertet, wenn x und y Ausdrücke vom booleschen Typ sind. Tatsächlich scheint der einzige Unterschied in diesem Fall darin zu bestehen, dass inx & y
, y immer ausgewertet wird.Antworten:
In den meisten Fällen
&&
und||
werden bevorzugt über&
und|
weil die ersteren sind kurzgeschlossen, so dass die Bewertung so schnell aufgehoben wird , wenn das Ergebnis klar ist.Beispiel:
Wenn zurückgegeben wird,
CanExecute
lautetfalse
der vollständige Ausdruckfalse
unabhängig vom Rückgabewert vonCanSave
. Aus diesem GrundCanSave
wird nicht ausgeführt.Dies ist unter folgenden Umständen sehr praktisch:
TryGetValue
Gibt zurück,false
wenn der angegebene Schlüssel nicht im Wörterbuch gefunden wird. Wegen des Kurzschlusses von&&
,value.Contains("test")
wird nur ausgeführt, wennTryGetValue
zurückkehrttrue
und somitvalue
nichtnull
. Wenn Sie stattdessen den bitweisen AND- Operator&
verwenden würden, würden Sie einen erhalten,NullReferenceException
wenn der Schlüssel nicht im Wörterbuch gefunden wird, da der zweite Teil des Ausdrucks in jedem Fall ausgeführt wird.Ein ähnliches, aber einfacheres Beispiel hierfür ist der folgende Code (wie von TJHeuvel erwähnt):
CanExecute
wird nur ausgeführt, wennop
nichtnull
. Wenn dies der Fallop
istnull
, wird der erste Teil von expression (op != null
) ausgewertetfalse
und die Auswertung von rest (op.CanExecute()
) wird übersprungen.Abgesehen davon, technisch gesehen , sie sind auch anders:
&&
und||
kann nur verwendet werden , auf derbool
Erwägung , dass&
und|
kann auf jedem integrierten Typ verwendet werden (bool
,int
,long
,sbyte
, ...), weil sie bitweise Operatoren sind.&
ist der bitweise UND- Operator und|
der bitweise ODER- Operator.Um genau zu sein, werden diese Operatoren (
&
,|
[und^
]) in C # als "logische Operatoren" bezeichnet (siehe C # -Spezifikation , Kapitel 7.11). Es gibt verschiedene Implementierungen dieser Operatoren:int
,uint
,long
undulong
, Kapitel 7.11.1):Sie werden implementiert , um die bitweise Ergebnis der Operanden und dem Betreiber zu berechnen, also
&
ist zu implementieren , um die bitweise logische berechnenAND
usw.Sie werden implementiert, um die logische Operation des zugrunde liegenden Aufzählungstyps auszuführen.
Das Ergebnis wird nicht mit bitweisen Berechnungen berechnet. Das Ergebnis wird im Wesentlichen anhand der Werte der beiden Operanden nachgeschlagen, da die Anzahl der Möglichkeiten so gering ist.
Da beide Werte für die Suche verwendet werden, wird diese Implementierung nicht kurzgeschlossen.
quelle
if(op != null && op.CanExecute())
. Da die zweite Ursache nicht bewertet wird, wenn die erste nicht wahr ist, ist dies gültig.TryGetValue
Beispiel beschrieben habe . Aber ja, es ist ein weiteres gutes Beispiel dafür.&
oder|
mit nicht-boolen Argumenten (dh was die Operatoren tun) zum Nutzen aller neuen Personen verwendet wird.Um sehr klar zu erklären, was dies bedeutet (obwohl die anderen Antworten darauf hinweisen - aber verwenden Sie wahrscheinlich eine Terminologie, die Sie nicht verstehen).
Der folgende Code:
Ist wirklich dazu zusammengestellt:
Wo der folgende Code genau so kompiliert wird, wie er dargestellt wird:
Dies wird als Kurzschluss bezeichnet. Im Allgemeinen sollten Sie immer
&&
und||
in Ihren Bedingungen verwenden.Bonuspunkte: Es gibt ein Szenario, in dem Sie nicht sollten. Wenn Sie sich in einer Situation befinden, in der die Leistung entscheidend ist (und dies ist Nano-Sekunden entscheidend ), verwenden Sie den Kurzschluss nur dann, wenn Sie müssen (z. B.
null
Prüfen) - da ein Kurzschluss eine Verzweigung / ein Sprung ist; Dies kann zu einer falschen Vorhersage der Verzweigung Ihrer CPU führen. ein&
ist viel billiger als&&
. Es gibt auch ein Szenario, in dem ein Kurzschluss tatsächlich die Logik brechen kann - sehen Sie sich meine Antwort an.Diatribe / Monolog : In Bezug auf die Zweigvorhersage, die am glücklichsten ignoriert wird. Zitat von Andy Firth (der seit 13 Jahren an Spielen arbeitet): "Dies ist möglicherweise eine niedrigere Ebene, die die Leute für nötig halten ... aber sie würden sich irren. Sie verstehen, wie die Hardware, die Sie für die Behandlung von Zweigen programmieren, dies kann." die Leistung in einem RIESIGEN Ausmaß beeinflussen ... weit mehr als die meisten Programmierer vielleicht zu schätzen wissen: Tod durch tausend Kürzungen. "
Hier ist ein Maßstab für die Ungläubigen. Führen Sie den Prozess am besten in RealTime / High aus, um die Auswirkungen des Schedulers zu verringern: https://gist.github.com/1200737
quelle
(x && y)
übersetzt dorthin,LOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;
wohin(x & y)
übersetzt wirdLOAD x; LOAD y; AND; BRANCH_FALSE;
. Ein Zweig gegen zwei.Logischer Operator (
||
und&&
) vs. bitweiser Operator (|
und&
).Der wichtigste Unterschied zwischen einem logischen Operator und einem bitweisen Operator besteht darin, dass ein logischer Operator zwei Boolesche Werte verwendet und einen Booleschen Wert erzeugt, während ein bitweiser Operator zwei Ganzzahlen verwendet und eine Ganzzahl erzeugt (Hinweis: Ganzzahlen bedeuten einen beliebigen integralen Datentyp, nicht nur int).
Um pedantisch zu sein, nimmt ein bitweiser Operator ein Bitmuster (z. B. 01101011) und führt ein bitweises UND / ODER für jedes Bit durch. Wenn Sie beispielsweise zwei 8-Bit-Ganzzahlen haben:
während ein logischer Operator nur funktioniert in
bool
:Zweitens ist es oft möglich, einen bitweisen Operator für bool zu verwenden, da true und false gleich 1 bzw. 0 sind. Wenn Sie true in 1 und false in 0 übersetzen, führen Sie eine bitweise Operation durch und konvertieren Sie dann Nicht-Null zu wahr und null zu falsch; Es kommt vor, dass das Ergebnis das gleiche ist, wenn Sie gerade einen logischen Operator verwendet haben (überprüfen Sie dies auf Übung).
Ein weiterer wichtiger Unterschied besteht darin, dass ein logischer Operator kurzgeschlossen wird . So sieht man in manchen Kreisen [1] oft Leute, die so etwas tun:
was übersetzt bedeutet: "Wenn eine Person existiert (dh nicht null ist), versuchen Sie, sie / ihn zu schlagen, und wenn der Schlag erfolgreich ist (dh wahr zurückgibt), dann machen Sie einen Siegestanz" .
Hatten Sie stattdessen einen bitweisen Operator verwendet:
wird übersetzt zu: "Wenn eine Person existiert (dh nicht null ist) und der Schlag erfolgreich ist (dh wahr zurückgibt), dann mache einen Siegestanz" .
Beachten Sie, dass im kurzgeschlossenen logischen Operator der
person.punch()
Code möglicherweise überhaupt nicht ausgeführt wird, wenn erperson
null ist. Tatsächlich würde in diesem speziellen Fall der zweite Code einen Nullreferenzfehler erzeugen, wenn erperson
null ist, da er versucht aufzurufen,person.punch()
unabhängig davon, ob die Person null ist oder nicht. Dieses Verhalten, den richtigen Operanden nicht auszuwerten, wird als Kurzschluss bezeichnet .[1] Einige Programmierer werden es ablehnen, einen Funktionsaufruf zu platzieren, der einen Nebeneffekt in einem
if
Ausdruck hat, während es für andere eine übliche und sehr nützliche Redewendung ist.Da ein bitweiser Operator jeweils mit 32-Bit arbeitet (wenn Sie sich auf einem 32-Bit-Computer befinden), kann dies zu einem eleganteren und schnelleren Code führen, wenn Sie eine große Anzahl von Bedingungen vergleichen müssen, z
Dasselbe mit logischen Operatoren zu tun, würde eine unangenehme Anzahl von Vergleichen erfordern:
Ein klassisches Beispiel für die Verwendung von Bitmustern und bitweisen Operatoren sind Unix / Linux-Dateisystemberechtigungen.
quelle
Im Falle von:
würde wie erwartet funktionieren.
Aber:
könnte möglicherweise eine Nullreferenzausnahme auslösen.
quelle
Kurz und einfach:
1 && 2
= wahr,weil
1 = wahr (nicht Null) in C
2 = wahr (nicht Null) in C.
true
ANDS logisch mittrue
zu gebentrue
.Aber
1 & 2
= 0 = falsch,weil
1 = 0001 in binär
2 = 0010 in binär
0001 UNDs bitweise mit 0010, um 0000 = 0 in Dezimalzahl zu ergeben.
Ebenso für || und | Betreiber auch ...!
quelle
1 && 2
ist illegal in C #&&
ist die Kurzschlussversion von&
.Wenn wir bewerten
false & true
, wissen wir bereits aus dem ersten Argument, dass das Ergebnis falsch sein wird. Die&&
Version des Operators gibt so schnell wie möglich ein Ergebnis zurück, anstatt den gesamten Ausdruck auszuwerten. Es gibt auch eine ähnliche Version des|
Operators||
.quelle
ist sicher
würde abstürzen, wenn die Liste nicht die richtige Größe hat.
quelle
C # -Betreiber sollten erklären, warum:
Wenn Sie im Wesentlichen zwei
&
oder zwei haben ,|
bedeutet dies, dass es sich eher um eine Bedingung als um eine logische handelt, sodass Sie den Unterschied zwischen den beiden erkennen können.& Operator hat ein Beispiel für die Verwendung eines
&
.quelle
OK, auf den Nennwert
die gleiche Antwort produzieren. Wenn Sie jedoch eine komplexere Frage haben, wie Sie gezeigt haben:
Wenn
a
es nicht wahr ist und vielleichtb
eine Funktion ist, bei der es losgehen muss, sich mit etwas verbinden, dies bekommen, das tun, eine Entscheidung treffen ... warum sich die Mühe machen? Zeitverschwendung, Sie wissen , dass es bereits fehlgeschlagen ist. Warum die Maschine ausschalten und besonders sinnlose Arbeit leisten?Ich habe es immer verwendet,
&&
weil ich das wahrscheinlichste Versagen zuerst, also weniger Berechnungen, vor dem Fortfahren gesetzt habe, wenn es keinen Sinn macht. Wenn es keine Möglichkeit gibt, weniger wahrscheinliche Entscheidungen vorherzusagen, z. B. einen Booleschen Wert, um die Ausgabe von Daten zu begrenzen, können Sie Folgendes tun:Wenn nicht
limit
, suchen Sie nicht nach dem Schlüssel, was länger dauern kann.quelle
Bei Verwendung in einem logischen Ausdruck wie einer if-Anweisung ist dies
&&
vorzuziehen, da die Auswertung von Ausdrücken beendet wird, sobald das erste falsche Ergebnis auftritt. Dies ist möglich, weil ein falscher Wert dazu führt, dass der gesamte Ausdruck falsch ist. Ähnlich (und wieder in logischen Ausdrücken)||
ist dies vorzuziehen, da die Auswertung von Ausdrücken beendet wird, sobald ein wahrer Ausdruck gefunden wird, da jeder wahre Wert dazu führt, dass der gesamte Ausdruck wahr ist.Wenn jedoch die Ausdrücke or-ed oder and-ed zusammen Nebenwirkungen haben und Sie möchten, dass all diese als Ergebnis Ihres Ausdrucks auftreten (unabhängig vom Ergebnis des logischen Ausdrucks), dann
&
und|
könnten verwendet werden. Umgekehrt können die Operatoren&&
und||
als Schutz vor unerwünschten Nebenwirkungen nützlich sein (z. B. ein Nullzeiger, der das Auslösen einer Ausnahme verursacht).Die Operatoren
&
und|
können auch mit ganzen Zahlen verwendet werden. In diesem Fall erzeugen sie ein ganzzahliges Ergebnis, bei dem es sich um die beiden Operanden handelt, die auf Bitebene zusammen -ed oder or-ed sind. Dies kann nützlich sein, wenn die Binärbits eines ganzzahligen Werts als Array von wahren und falschen Werten verwendet werden. Um zu testen, ob ein bestimmtes Bit ein- oder ausgeschaltet ist, wird eine Bitmaske bitweise mit dem Wert versehen. Um ein Bit einzuschalten, kann dieselbe Maske bitweise mit dem Wert verknüpft werden. Zum Schluss, um ein bisschen auszuschalten, wird das bitweise Komplement (unter Verwendung~
) einer Maske bitweise und mit dem Wert bearbeitet.In anderen Sprachen als C # muss mit den logischen und bitweisen Modi von & und | vorsichtig umgegangen werden. Im obigen Code ist der
if
bedingte Ausdruck der Anweisung(a & 4) != 0
eine sichere Möglichkeit, diese Bedingung auszudrücken. In vielen C-ähnlichen Sprachen können bedingte Anweisungen einfach ganzzahlige Werte von Null als falsch und ganzzahlige Werte ungleich Null als wahr behandeln. (Der Grund hierfür liegt in den verfügbaren Anweisungen für bedingte Verzweigungsprozessoren und in ihrer Beziehung zum Null-Flag, das nach jeder Ganzzahloperation aktualisiert wird.)ìf
Der Test der Anweisung für Null kann also entfernt und die Bedingung auf verkürzt werden(a & 4)
.Dies kann zu Verwirrung und möglicherweise sogar zu Problemen führen, wenn Ausdrücke mit bitweisen und Operator-Rückgabewerten kombiniert werden, für die keine Bits vorhanden sind. Betrachten Sie das folgende Beispiel, in dem die Nebenwirkungen von zwei Funktionen gewünscht werden, bevor Sie überprüfen, ob beide erfolgreich waren (wie von ihnen definiert, und einen Wert ungleich Null zurückgeben):
Wenn in C
foo()
1 undbar()
2 zurückgegeben wird, wird das "Etwas" nicht ausgeführt, da1 & 2
es Null ist.C # erfordert bedingte Anweisungen
if
, die einen booleschen Oeprand haben sollen, und die Sprache erlaubt nicht, dass ein ganzzahliger Wert in einen booleschen Wert umgewandelt wird. Der obige Code würde also Compilerfehler erzeugen. Es würde korrekter wie folgt ausgedrückt:quelle
Wenn Sie ein Oldtimer-C-Programmierer sind, seien Sie vorsichtig . C # hat mich wirklich überrascht.
MSDN sagt für den
|
Betreiber:(Der Schwerpunkt liegt bei mir.) Boolesche Typen werden speziell behandelt, und in diesem Zusammenhang macht die Frage erst Sinn, und der Unterschied besteht darin, wie andere bereits in ihren Antworten dargelegt haben:
und was vorzuziehen ist, hängt von vielen Dingen wie Nebenwirkungen, Leistung und Lesbarkeit des Codes ab, aber im Allgemeinen sind die Kurzschlussoperatoren auch deshalb vorzuziehen, weil sie von Menschen mit einem ähnlichen Hintergrund wie mir besser verstanden werden.
Der Grund ist: Ich würde so argumentieren: Da es in C keinen echten booleschen Typ gibt, können Sie den bitweisen Operator verwenden
|
und sein Ergebnis in einer if-Bedingung als wahr oder falsch bewerten lassen. Dies ist jedoch die falsche Einstellung für C #, da es bereits einen Sonderfall für boolesche Typen gibt.quelle
Dies ist wichtig, denn wenn die Kosten für die Evaluierung von bool2 (zum Beispiel) hoch sind, bool1 jedoch falsch, haben Sie sich mit && over & einiges an Rechenaufwand erspart
quelle
Weil
&&
und||
für die Flusskontrolle genauso verwendet werden wie sieif/else
sind. Es geht nicht immer um Bedingungen. Es ist durchaus sinnvoll, wie zu schreiben , eine Erklärung, nicht als einif
oder einewhile
bedingte, die folgenden:oder auch
Es ist nicht nur so, dass diese einfacher zu tippen sind als die entsprechenden
if/else
Versionen. Sie sind auch viel einfacher zu lesen und zu verstehen.quelle
&& und & bedeuten zwei sehr unterschiedliche Dinge und geben Ihnen zwei unterschiedliche Antworten.
1 && 2
ergibt 1 ("wahr")1 & 2
ergibt 0 ("falsch")&&
ist ein logischer Operator - es bedeutet "wahr, wenn beide Operanden wahr sind"&
ist ein bitweiser Vergleich. Es bedeutet "Sag mir, welche der Bits in beiden Operanden gesetzt sind".quelle
1 && 2
gibt einen Compilerfehler aus: "Fehler 4 Operator '&&' kann nicht auf Operanden vom Typ 'int' und 'int' angewendet werden"Der schnellste (und etwas heruntergekommenste) Weg, dies Leuten zu erklären, die dabei nicht die genauen Operationen des Codes kennen MÜSSEN, ist
&& überprüft jede dieser Bedingungen, bis eine falsche gefunden wird und das gesamte Ergebnis als falsch zurückgegeben wird
|| überprüft jede dieser Bedingungen, bis sie ein wahres Ergebnis findet und das gesamte Ergebnis als wahr zurückgibt.
& macht MATHS-basierte Apon BEIDE / ALLE Bedingungen und befasst sich mit dem Ergebnis.
| macht MATHS-basierte Apon BEIDE / ALLE Bedingungen und befasst sich mit dem Ergebnis.
Ich bin noch nie auf einen Punkt gestoßen, an dem ich & oder | verwenden musste innerhalb einer if-Anweisung. Ich benutze es meistens, um Hexadezimalwerte durch bitweise Verschiebung in seine Komponentenfarben zu zerschneiden.
Z.B:
Innerhalb dieser Operation zwingt "& 0xFF", nur den Binärwert zu betrachten. Ich habe persönlich keine Verwendung für | gefunden doch trotzdem.
quelle
Einfach,
if exp1 && exp2
Wenn exp1 ist
flase
, überprüfen Sie nicht exp2aber
if exp1 & exp2
wenn exp1 ist
false
Odertrue
überprüfen Sie exp2und selten verwenden Leute,
&
weil sie selten exp2 überprüfen wollen, ob exp1 istfalse
quelle