C # bedingte UND (&&) ODER (||) Priorität

77

Bei meiner Arbeit geraten wir ständig in unnötige Codierungsargumente. Heute habe ich gefragt, ob bedingtes UND (&&) oder ODER (||) eine höhere Priorität haben. Einer meiner Mitarbeiter bestand darauf, dass sie den gleichen Vorrang hatten, ich hatte Zweifel, also habe ich nachgeschlagen.

Laut MSDN hat AND (&&) eine höhere Priorität als OR (||). Aber können Sie es einem skeptischen Mitarbeiter beweisen?

http://msdn.microsoft.com/en-us/library/aa691323(VS.71).aspx

bool result = false || true && false; // --> false
// is the same result as
bool result = (false || true) && false; // --> false
// even though I know that the first statement is evaluated as 
bool result = false || (true && false); // --> false

Meine Frage ist also, wie Sie mit Code beweisen, dass AND (&&) eine höhere Priorität hat als OR (||)? Wenn Ihre Antwort lautet, dass es keine Rolle spielt, warum ist es dann so in der Sprache aufgebaut?

Josiah Ruddell
quelle
18
So ist es in der Sprache, weil sie eine Entscheidung treffen müssen. Persönlich ist es mir egal, welche Vorrang hat; Ich würde Klammern verwenden, um sicherzustellen, dass ich das erwartete Ergebnis erhalte. Es geht nicht darum, warum es tut, was es tut; Es geht darum, herauszufinden, was der Code tut, wenn Sie Wochen, Monate oder Jahre später darauf zurückgreifen.
Jeff Siver
25
@ Jeff: Das stimmt nicht. Es gibt eine mathematische Grundlage für diese Entscheidung - sie heißt Boolesche Algebra .
EFraim
4
@TheSteve: Kurzschluss hat keinen Einfluss auf das Ausdrucksergebnis. Es betrifft nur Nebenwirkungen.
EFraim
8
Die Tatsache, dass Sie sogar darüber nachdenken müssen, bedeutet, dass Sie sich nicht darauf verlassen sollten, dass der nächste weiß, wenn es eine Frage gibt, die möglicherweise jemand im Büro 3 Sekunden lang darüber nachdenken muss, dann investieren Sie die 0,5 Sekunden, um sie hinzuzufügen a (und a)
Bill K
34
Lassen Sie mich sehen, ob ich das klargestellt habe. Ihr Mitarbeiter glaubt an die Sprache. Dieser Überzeugung wird sowohl durch die Spezifikation als auch durch die Implementierung widersprochen. Ihr Anspruch steht im Einklang mit der Spezifikation und der Implementierung. Warum versuchen SIE, einen Beweis zu konstruieren? Die Beweislast liegt bei der Person, die den verrückten Glauben hat, nicht bei der Person, die den vernünftigen Glauben hat. Ich würde keine Zeit mehr damit verschwenden. Wenn sie ihre Zeit damit verbringen wollen, etwas Falsches zu beweisen, lassen Sie sie.
Eric Lippert

Antworten:

116

Ändern Sie das erste false durch true. Ich weiß, es scheint dumm zu sein (wahr || wahr), aber es beweist Ihren Standpunkt.

bool result = true || true && false;   // --> true 
     result = (true || true) && false; // --> false
     result = true || (true && false); // --> true
Francis B.
quelle
13
Kurzschlüsse treten nur dann auf, wenn das Ergebnis des Booleschen Ausdrucks bekannt ist. Kurzschluss kann das Ergebnis eines booleschen Ausdrucks nicht ändern.
Kapitän Segfault
5
@ James, nein, würde es nicht .. Wenn || hätte eine höhere Priorität, dann wäre der Ausdruck gleichbedeutend mit (wahr || wahr) && falsch => falsch, nicht wahr, weil nach der Bewertung {wahr || wahr) als wahr, was übrig bleiben würde, ist wahr & falsch, was
KEINEN
6
@ James, Nein, wenn || hätte eine höhere Priorität, würde der clr dies als (wahr oder wahr) && falsch bewerten. also würde es zuerst auswerten (wahr || wahr). Innerhalb dieses Ausdrucks tritt ja ein Kurzschluss auf, da für einen ODER-Ausdruck, wenn der erste Teil wahr ist, es nicht erforderlich ist, den zweiten Teil zu bewerten. Das ergibt also wahr. Jetzt haben wir wahr && falsch. Bei && -Operationen tritt ein Kurzschluss nur auf, wenn der erste Teil FALSE ist, was in diesem Fall nicht der Fall ist. Daher müssen beide Teile wahr sein, damit A && B als wahr ausgewertet wird. Also bewertet es beide Teile und kommt mit falsch
Charles Bretana
14
Könnten wir einfach all diesen Unsinn stoppen, der sich ad nauseum zu wiederholen scheint?! Wiederholen Sie mit mir: KURZSCHALTUNG ÄNDERT DAS ERGEBNIS NICHT. Kurzschluss gilt nur, wenn das Ergebnis bereits bekannt ist. KURZSCHLUSS NUR BEEINFLUSST NEBENWIRKUNGEN
EFraim
9
@comecme Das ist nicht das Ergebnis eines Kurzschlusses, sondern einer Änderung der Betriebsreihenfolge. Der Operator & hat eine höhere Priorität als der Operator | Operator, so würde sich der erste Ausdruck wie verhalten true | (false & false). Dies würde wahr , weil bewertet false & false = false, dann false | true = true. Die | Der Operator hat eine höhere Priorität als der Operator &&, daher würde sich der zweite Ausdruck wie folgt verhalten (true | false) && false. Dies würde bewerten zu falsch , weil true | false = truedann true && false = false.
Abion47
11

Wenn Sie ihn wirklich ausflippen wollen, versuchen Sie:

bool result = True() | False() && False();

Console.WriteLine("-----");
Console.WriteLine(result);

static bool True()
{
    Console.WriteLine(true);
    return true;
}

static bool False()
{
    Console.WriteLine(false);
    return false;
}

Dies wird gedruckt:

True
False
False
-----
False

Bearbeiten:

Als Antwort auf den Kommentar:

In C # |ist ein logischer Operator, der dieselbe boolesche Logik wie ausführt ||, jedoch keinen Kurzschluss verursacht. Auch in C # hat der |Operator eine höhere Priorität als beide ||und &&.

Wenn Sie die Werte ausdrucken , können Sie sehen, dass bei Verwendung des typischen ||Operators nur der erste Truegedruckt wird - gefolgt vom Ergebnis des Ausdrucks, der auch gewesen wäre True.

Aber wegen des höheren Vorrangs |, das true | falseausgewertet wird zuerst (was true) und dann das Ergebnis &&mit ed falseauf Ertrag false.

Ich habe nicht versucht, die Reihenfolge der Bewertung anzuzeigen, sondern nur die Tatsache, dass die rechte Hälfte des |Bewertungszeitraums bewertet wurde, in dem dies normalerweise nicht der Fall wäre :)

John Rasch
quelle
1
ein. Warum booleschen und bitweisen Operator mischen? b. Warum bestehen Sie darauf, es zu drucken? Was hat die Reihenfolge der Bewertung damit zu tun?
EFraim
2
Antwort auf Antwort: | ist immer noch binär. Es ist nur so, dass es für bool die gewünschte Operation ausführt - wie in C ++. Um dies zu verdeutlichen, dokumentiert MS es als logisch für Bools. Aber meiner Meinung nach trübt es nur Wasser.
EFraim
1
Dies wäre ein amüsanter Streich. :)
James
1
Also, wenn Sie ändern , ||um |das und zu verlassen &&, das Ergebnis des Ausdrucks ändert sich von wahr zu falsch? Normalerweise würden Sie also entweder |zusammen mit &oder ||zusammen mit verwenden &&.
Comecme
6

Würde dir das nicht das bringen, wonach du suchst? Oder vielleicht fehlt mir etwas ...

bool result = true || false && false;
Max Schmeling
quelle
Dies unterscheidet zwischen && mit höherer Priorität und || mit höherer Priorität, unterscheidet aber nicht zwischen || mit höherer Priorität und && und || mit gleicher Priorität. Denken Sie daran, dass Operatoren, die Vorrang haben, einfach von links nach rechts ausgewertet werden.
Tyler McHenry
1
Ich sollte jedoch sagen, dass dies als Beweis für C # (oder wirklich jede normale Sprache) funktioniert, da das tatsächliche Ergebnis, das Sie erhalten, eindeutig ist. Es ist einfach keine allgemeine Methode, um die relative Priorität zu ermitteln, falls Sie mit einer esoterischen Sprache konfrontiert sind, die absichtlich der Booleschen Algebra widerspricht.
Tyler McHenry
5

Sie beweisen es nicht mit Code, sondern mit Logik. AND ist eine boolesche Multiplikation, während OR eine boolesche Addition ist. Welches hat nun einen höheren Vorrang?

EFraim
quelle
10
In einigen Sprachen tut dies keiner (z. B. Smalltalk). Analogien können täuschen.
Pavel Minaev
11
Ich weiß nichts über den anderen Downvoter, aber ich habe downvotiert, weil dies nichts mit der Frage zu tun hat. Es passt zusammen ... aber jeder kann eine Sprache Foo # entwerfen, in der dies nicht wahr ist. Wie würde Ihr " Beweis mit Logik" dann funktionieren? Es könnte erklären, warum diese Priorität gewählt wurde, aber es hilft nicht festzustellen, dass sich der von mir installierte Compiler tatsächlich so verhält.
Roman Starkov
2
@romkyns: Es hat alles mit der Sprache zu tun. Die Regeln von C und C ++ leiten sich aus den Gesetzen der Algebra ab. Deshalb hat + eine geringere Priorität als *. Sie können argumentieren, was Sie wollen, aber Sie sind sowohl falsch als auch widerlich. Ihr Compiler verhält sich gemäß der Sprachspezifikation und die Sprachspezifikation
basiert
3
QED? Wissen Sie, was es bedeutet , etwas zu beweisen ? Die Sprache könnte bestimmt den Gesetzen der Algebra zu folgen, aber wie wollen Sie beweisen , dass zwischen dieser Absicht und der riesigen Menge an Engineering - Aufwand, niemand vermasselte und verletzte es aus Versehen oder die Spezifikation falsch verstanden , wenn die Vorrangregeln zu implementieren? (unwahrscheinlich, aber nicht unmöglich)
Roman
3
Ich denke, der Punkt, den Sie ansprechen, ist gültig. Es ist nur so, dass er nicht als "Beweis" qualifiziert ist, bei dem ein Beweis viel strenger ist, als nur zu erklären, wie und warum die Sprachdesigner beschlossen haben, Dinge zu tun. "Sie haben es auf Algebra basiert, daher funktioniert es notwendigerweise wie Algebra" ist kein strenger Beweis (und es tatsächlich so zu sagen, ist logisch ungültig).
Dave Cousineau
1

false || Wahr, wahr

Erträge: wahr

false && true || wahr

Erträge: wahr

vegetarisch
quelle
Die erste Anweisung gibt true zurück, unabhängig davon, in welcher Reihenfolge Sie die Operationen ausführen. Die zweite Anweisung gibt nur false zurück, wenn || wird zuerst ausgewertet. Da es true zurückgibt, wird entweder && zuerst ausgewertet, oder sie haben dieselbe Priorität und werden von links nach rechts ausgewertet. Eine dritte Aussage true || true && false(die auch true zurückgibt) kann nur dann wahr sein, wenn && zuerst ausgewertet wird.
CodeHxr
-5

Sie können das Endergebnis nicht einfach anzeigen, wenn Ihre booleschen Ausdrücke kurzgeschlossen werden. Hier ist ein Ausschnitt, der Ihren Fall regelt.

Es basiert auf der Implementierung von & und | Von && und || verwendete Operatoren, wie in MSDN 7.11 angegeben. Bedingte logische Operatoren

public static void Test()
{
    B t = new B(true);
    B f = new B(false);

    B result = f || t && f;

    Console.WriteLine("-----");
    Console.WriteLine(result);
}

public class B {
    bool val;
    public B(bool val) { this.val = val; }
    public static bool operator true(B b) { return b.val; }
    public static bool operator false(B b) { return !b.val; }
    public static B operator &(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " & " + rhs.ToString());
        return new B(lhs.val & rhs.val); 
    }
    public static B operator |(B lhs, B rhs) { 
        Console.WriteLine(lhs.ToString() + " | " + rhs.ToString());
        return new B(lhs.val | rhs.val); 
    }
    public override string ToString() { 
        return val.ToString(); 
    }
}

Die Ausgabe sollte zeigen, dass && zuerst vor || ausgewertet wird.

True & False
False | False
-----
False

Versuchen Sie es für zusätzlichen Spaß mit result = t || t && f und sehen, was mit Kurzschluss passiert.

James
quelle
6
Kurzschluss hat nichts mit Ausdrucksergebnis zu tun. Können wir einfach darüber hinwegkommen?
EFraim