2009-03-26 7 views
44

Ok, ich habe über diese einige Male so gelesen, aber ich bin noch eine klare, leicht zu verstehen (und unvergessliche) Art und Weise zu hören, den Unterschied zwischen lernen:Eine klare, laienhafte Erklärung des Unterschieds zwischen | und || in C#?

if (x | y) 

und

if (x || y) 

..im Kontext von C#. Kann mir bitte jemand helfen, diese grundlegende Wahrheit zu lernen, und wie C# sie speziell behandelt (weil sie das Gleiche zu tun scheinen). Wenn der Unterschied, den ein bestimmter Codeabschnitt zwischen ihnen hat, irrelevant ist, was sollte ich als Best-Practice-Standard verwenden?

Antwort

83

|| ist der Operator logisch-oder. Siehe here. Es wird true ausgewertet, wenn mindestens einer der Operanden wahr ist. Sie können es nur mit booleschen Operanden verwenden; Es ist ein Fehler, es mit ganzzahligen Operanden zu verwenden.

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

| ist die oder Operator. Siehe here. Wenn es auf boolesche Typen angewendet wird, wird true ausgewertet, wenn mindestens einer der Operanden wahr ist. Wenn es auf ganzzahlige Typen angewendet wird, wird eine andere Zahl ausgewertet. Bei dieser Zahl ist jedes Bit auf 1 gesetzt, wenn mindestens einer der Operanden ein entsprechendes Bit gesetzt hat.

// 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 

Für Boolesche Operanden, a || b ist identisch-a | b, mit der einzigen Ausnahme, dass b nicht ausgewertet, wenn a wahr ist. Aus diesem Grund wird || als "Kurzschluss" bezeichnet.

Wenn der Unterschied, den ein bestimmter Codeabschnitt zwischen ihnen hat, irrelevant ist, was sollte ich als Best-Practice-Standard verwenden?

Wie bereits erwähnt, ist der Unterschied nicht irrelevant, so dass diese Frage teilweise strittig ist. Was eine "Best Practice" betrifft, gibt es keine: Sie verwenden einfach den Operator, der der richtige ist. Im Allgemeinen bevorzugen die Leute || über | für boolesche Operanden, da Sie sicher sein können, dass es keine unnötigen Nebenwirkungen erzeugt.

10

Sie sind nicht das Gleiche. Einer ist bitweises ODER und eins ist logisches ODER.

X || Y, ist ein logisches oder, bedeutet dasselbe wie "X oder Y" und gilt für bool-Werte. Es wird in Bedingungen oder Tests verwendet. X und Y können in diesem Fall durch jeden Ausdruck ersetzt werden, der zu einem Bool ausgewertet wird. Beispiel:

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

Die Klausel wird als wahr ausgewertet, wenn eine der beiden Bedingungen zutrifft. Wenn die erste Bedingung wahr ist (wenn die Datei existiert), braucht die zweite Bedingung nicht und wird nicht ausgewertet.

Das Einzelrohr (|) ist ein bitweises ODER. Um zu wissen, was das bedeutet, müssen Sie verstehen, wie Zahlen im Computer gespeichert sind. Angenommen, Sie haben eine 16-Bit-Menge (Int16), die den Wert 15 enthält. Sie wird tatsächlich als 0x000F (in hex) gespeichert, was in binärem Format gleich 0000 0000 0000 1111 ist. Das bitweise OR nimmt zwei Größen und ODER jedes Paar korrespondierender Bits zusammen, so dass, wenn das Bit in jeder Menge 1 ist, es 1 im Ergebnis ist. Wenn also a = 0101 0101 0101 0101 (was 0x5555 in Hex ergibt) und b = 1010 1010 1010 1010 (was 0xAAAA ist), dann ist a | b = 1111 1111 1111 1111 = 0xFFFF.

Sie können in C# bitweise ORs (single pipe) verwenden, um zu testen, ob mindestens ein bestimmter Bitsatz aktiviert ist. Sie könnten dies tun, wenn Sie zum Beispiel 12 boolesche oder binäre Werte haben, für die Sie testen möchten, und sie sind alle unabhängig. Angenommen, Sie haben eine Studenten-Datenbank. Eine Reihe von unabhängigen booleschen Werten könnte Dinge wie männlich/weiblich, zu Hause/auf dem Campus, aktuell/nicht aktuell, angemeldet/nicht angemeldet usw. sein. Anstatt ein boolesches Feld für jeden dieser Werte zu speichern, könnten Sie speichern nur ein einziges Bit für jeden. Der Mann/Frau sein könnte Bit 1 eingeschrieben/könnte etwas nicht sein 2.

Dann können Sie

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

als Test, um zu sehen, wenn keine Bits eingeschaltet sind, mit Ausnahme des „Student ist männlich "Bit, das ignoriert wird. Hä? Nun, das bitweise OR gibt eine 1 für jedes Bit zurück, das in einer der beiden Zahlen eingeschaltet ist. Wenn das Ergebnis des bitweisen ODER über = 0x0001 ist, bedeutet dies, dass im Bitfeld keine Bits eingeschaltet sind, außer vielleicht das erste Bit (0x0001), aber Sie können nicht sicher sagen, ob das erste Bit eingeschaltet ist, weil es ist maskiert.

Es gibt eine entsprechende & & und &, die logische UND und bitweise UND ist. Sie haben das analoge Verhalten.

können Sie

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

sehen verwenden, wenn das erste Bit auf in einem Bitfeld gedreht wird.

EDIT: Ich kann nicht glauben, dass ich dafür gewählt wurde!

+0

| hat eine andere Bedeutung in C#. Das könnte der Grund sein. – jalf

+1

Es ist mehr überraschend, dass Sie gewählt wurden, da die Antwort für die Frage völlig irrelevant ist ... – Guffa

4

| ist ein bitweiser OR-Operator (numerisch, Ganzzahl). Es funktioniert, indem die Zahlen in binäre umgewandelt werden und ein OR für jede der entsprechenden Ziffern. dann wieder, Zahlen sind bereits im Computer binär dargestellt, so dass eine solche Umwandlung wirklich nicht zur Laufzeit stattfindet;)

|| ist ein logischer OR-Operator (boolesch). Es funktioniert nur bei wahren und falschen Werten.

2

Der erste bitweise Operator arbeitet mit zwei numerischen Werten und führt zu einem dritten.

Wenn Sie Binärgrößen

a = 0001001b; 
b = 1000010b; 

dann

a | b == 1001011b; 

Das heißt, ein Bit im Ergebnis ist 1, wenn es auch 1 in einem der Operanden ist. (Mein Beispiel verwendet aus Gründen der Übersichtlichkeit 8-Bit-Zahlen.)

Das "Doppelrohr" || ist ein logischer OR-Operator, der zwei boolesche Werte annimmt und zu einem dritten führt.

5

Gute Antworten, aber lassen Sie mich hinzufügen, dass die rechten Ausdrücke für || nicht ausgewertet wird, wenn der linke Ausdruck true ist. Beachten Sie dies in Fällen, in denen die Bewertungsbedingungen a) leistungsintensiv sind oder b) Nebenwirkungen hervorrufen (selten).

5

Im Gegensatz zu dem, was die meisten Antworten bisher sagen, ist die Bedeutung nicht genau das gleiche wie in C++.

Für zwei beliebige Ausdrücke A und B, die boolesche Werte auswerten, A || B und A | B mache fast dasselbe.

A | B wertet sowohl A und B aus, und wenn einer von ihnen als wahr auswertet, ist das Ergebnis wahr.

A || B macht fast dasselbe, außer dass es zuerst A bewertet und dann nur B auswertet, wenn es notwendig ist. Da der gesamte Ausdruck wahr ist, wenn entweder A oder B wahr ist, muss B überhaupt nicht getestet werden, wenn A wahr ist. Also || Kurzschlüsse und überspringt, wenn möglich, den zweiten Operanden, wobei | Betreiber wird immer beide bewerten.

Die | Operator wird nicht oft verwendet, und oft wird es keinen Unterschied machen. Der einzige gemeinsame Fall, dass ich denken kann, wo es einen Unterschied machen würde, ist dies:

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

} 

Das funktioniert, weil die DoStuff() Member-Funktion wird nie, wenn der linke Test nicht genannt. Das heißt, wenn foo null ist, rufen wir DoStuff nicht auf. (was uns eine NullReferenceException geben würde).

Wenn wir die | Operator würde DoStuff() aufgerufen werden, unabhängig davon, ob foo null war oder nicht.

Bei Ganzzahlen nur die | Operator ist definiert und ist ein bitweises ODER, wie die anderen Antworten beschreiben. Die || operator ist jedoch nicht für Integer-Typen definiert, daher ist es schwierig, sie in C# zu mischen.

+0

Der Code, den Sie geschrieben haben, ist falsch. Die korrekte Form ist: 'if (foo == null || foo.DoStuff())'. Also, wenn 'foo == null', gibt der Ausdruck 'wahr' zurück, ohne weiter auszuwerten; andernfalls ist 'foo' nicht null, daher gibt der erste Teil false zurück und der zweite Teil wird ausgewertet, und das kann der Fall sein, da in diesem Fall' foo' nicht null ist. –

3

Das folgende würde in C/C++ funktionieren, weil es keine erstklassige Unterstützung für Boolesche Zeichen hat, behandelt es jeden Ausdruck mit "ein" Bit auf ihnen als wahr, andernfalls falsch. Tatsächlich würde der folgende Code in C# oder Java nicht funktionieren, wenn x und y numerische Typen sind.

if (x | y) 

So ist die explizite Version des obigen Code ist:

if ((x | y) != 0) 

In C, jeder Ausdruck, der eine "On" Bit auf sich, die Ergebnisse auf true

int haben würde i = 8 ;

wenn (i) // gültig in C ergibt true

int Freude = -10;

if (Freude) // vaild in C ergibt, auf true

Nun, zurück zu C#

Wenn x und y numerischer Art sind, Ihr Code: if (x | y) wird nicht funktionieren. Hast du versucht es zu kompilieren? Es funktioniert nicht

Aber für Ihren Code, den ich annehmen könnte x und y sind Boolean Typen, so wird es funktionieren, so dass der Unterschied zwischen | und || Für boolesche Typen ist das || ist kurzgeschlossen, der | ist nicht.Der Ausgang der folgenden:

static void Main() 
    { 


     if (x | y) 
      Console.WriteLine("Get"); 

     Console.WriteLine("Yes"); 

     if (x || y) 
      Console.WriteLine("Back"); 

     Console.ReadLine(); 
    } 


    static bool x 
    { 
     get { Console.Write("Hey"); return true; } 
    } 

    static bool y 
    { 
     get { Console.Write("Jude"); return false; } 
    } 

ist:

HeyJudeGet 
Yes 
HeyBack 

Jude nicht zweimal gedruckt werden, die || ist ein Boolescher Operator, viele C-abgeleitete Sprachen Boolesche Operatoren sind kurzgeschlossen, boolesche Ausdrücke sind leistungsfähiger, wenn sie kurzgeschlossen sind.

Wie für Laien Begriffe, wenn Sie sagen, kurzgeschlossen, zum Beispiel in || (oder Operator), wenn der erste Ausdruck bereits wahr ist, muss der zweite Ausdruck nicht ausgewertet werden. Beispiel: if (answer == 'y' || answer == 'Y'), wenn der Benutzer ein kleines y drückt, muss das Programm den zweiten Ausdruck nicht auswerten (answer == 'Y'). Das ist Kurzschluss.

In meinem obigen Beispielcode ist X wahr, also das Y on || Operator wird nicht weiter ausgewertet, daher keine zweite "Jude" -Ausgabe.

Verwenden Sie diese Art von Code nicht in C#, auch wenn X und Y Boolesche Typen sind: if (x | y). Nicht performant.

42

Wenn mit boolean Operanden der | Operator ist ein logischer Operator ebenso ||, aber der Unterschied ist, dass der || Operator Kurzschlussauswertung funktioniert und die | Betreiber nicht.

Das bedeutet, dass der zweite Operand immer mit dem Operator | ausgewertet wird, der zweite Operand jedoch nur mit dem Operator || ausgewertet wird, wenn der erste Operand als false ausgewertet wird.

Das Ergebnis des Ausdrucks ist für beide Operatoren immer gleich, aber wenn die Auswertung des zweiten Operanden bewirkt, dass sich etwas anderes ändert, ist dies nur garantiert, wenn Sie den Operator | verwenden.

Beispiel:

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. 

Der Kurzschluss Auswertung des || Operators verwendet werden kann kürzeren Code zu schreiben, als der zweite Operand nur dann ausgewertet wird, wenn der erste Operand wahr ist. Statt wie dieses schreiben:

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); 
    } 
} 

können Sie so schreiben:

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

Der zweite Operand nur dann, wenn der erste falsch ausgewertet wird, ist, so wissen Sie, dass Sie sicher den String Referenz verwenden können in der zweite Operand kann nicht null sein, wenn der zweite Operand ausgewertet wird. In den meisten Fällen möchten Sie den Operator || anstelle des Operators | verwenden. Wenn der erste Operand falsch ist, muss der zweite Operand nicht ausgewertet werden, um das Ergebnis zu erhalten. Außerdem wissen viele Leute (offensichtlich) nicht, dass Sie den Operator | mit booleschen Operanden verwenden können, so dass sie verwirrt werden würden, wenn sie so im Code verwendet werden.

+3

Ich wünschte, ich könnte +10 geben, das ist die relevanteste Antwort in Bezug auf C#. Während alle anderen technisch korrekt sind, ignorieren sie die Tatsache, dass die Frage sich auf boolesche Logik in C# bezieht. –

+0

Sollte das nicht "str! = Null" sein? – Les

+0

Nein, dieser Teil ist korrekt, aber der erste Teil scheint mir falsch zu sein: int a = 0; int b = 0; bool x = (a! = 0 || ++ b! = 0); // hier ist b noch 0, da der Operand "++ b! = 0" nicht ausgewertet wurde Aber a == 0, also wird die erste Anweisung auf false ausgewertet und so der 2. Teil ausgewertet. – Davy8

2

Ohne in die Details in irgendeiner Weise, Form oder Form einzutauchen, ist hier eine echte Laienversion.

Denken Sie an "|" als geradliniges "oder" auf Englisch; denke an "||" als "oder sonst" in Englisch.

Ähnlich denken Sie an "&" als "und" in Englisch; denke an "& &" als "und auch" in Englisch.

Wenn Sie einen Ausdruck lesen, der diese Begriffe verwendet, sind sie oft viel sinnvoller.

1

Obwohl es bereits gesagt und richtig beantwortet wurde, dachte ich, dass ich die Antwort eines echten Laien hinzufügen würde, da ich viel Zeit auf dieser Site habe :). Plus Ich werde das Beispiel & vs. & & hinzufügen, da es das gleiche Konzept ist

| vs ||

Grundsätzlich neigen Sie dazu, die || wenn Sie nur den zweiten Teil WENN den ersten Teil bewerten wollen, ist es FALSCH. So folgt aus:

if (func1() || func2()) {func3();} 

ist die gleiche wie

if (func1()) 
{ 
    func3(); 
} 
else 
{ 
    if (func2()) {func3();} 
} 

Dies ist ein Weg sein kann, die Verarbeitungszeit zu sparen. Wenn die Verarbeitung von func2() sehr lange dauert, möchten Sie dies nicht tun, wenn func1() bereits erfüllt ist.

& vs & &

Im Fall von & vs. & & es ist eine ähnliche Situation, wo man nur den zweiten Teil bewerten, wenn der erste Teil TRUE ist. Zum Beispiel dieses:

if (func1() && func2()) {func3();} 

ist die gleiche wie

if (func1()) 
{ 
    if (func2()) {func3();}} 
} 

Dies kann da func2 notwendig sein() auf func1 depend() zuerst wahr zu sein. Wenn Sie & und func1() als falsch ausgewertet haben, würde & trotzdem func2() ausführen, was einen Laufzeitfehler verursachen könnte.

Jeff der Laie

2

Dringend empfohlen, this Artikel von Dotnet Mob

Für OR logische Operation zu lesen, wenn irgendetwas davon ist der Operanden true ausgewertet wird dann gesamte Ausdruck auf true ausgewertet

das ist was || Operator tut - es überspringt die verbleibende Bewertung, wenn es eine wahre gefunden hat. Während | Der Operator evaluiert seine vollständigen Operanden, um den Wert des gesamten Ausdrucks zu beurteilen.

if(true||Condition1())//it skip Condition1()'s evaluation 
{ 
//code inside will be executed 
} 
if(true|Condition1())//evaluates Condition1(), but actually no need for that 
{ 
//code inside will be executed 
} 

Es ist besser, einen Kurzschluss-Version Logischer Operator zu verwenden Ob es OR (||) oder AND (& &) Operator.


Betrachten Sie den folgenden Code Snippet

int i=0; 
if(false||(++i<10))//Now i=1 
{ 
//Some Operations 
} 
if(true||(++i<10))//i remains same, ie 1 
{} 

Dieser Effekt wird Nebenwirkung genannt, tatsächlich in der rechten Seite des Ausdrucks in kurzgeschlossen logischen Operatoren

Referenz gesehen: Short-circuit Evaluation in C#

Verwandte Themen