C # умовний І (&&) АБО (||) пріоритет


77

Ми постійно потрапляємо в непотрібні аргументи кодування на моїй роботі. Сьогодні я запитав, чи має вищий пріоритет умовне І (&&) чи АБО (||). Один із моїх колег наполягав на тому, що вони мали однаковий пріоритет, у мене були сумніви, тому я шукав це.

Відповідно до MSDN AND (&&) має вищий пріоритет, ніж OR (||). Але, чи можете ви довести це скептично налаштованому колезі?

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

Тож моє питання полягає в тому, як довести за допомогою коду, що AND (&&) має вищий пріоритет, ніж OR (||)? Якщо ваша відповідь не має значення, то чому так побудовано в мові?


18
Це так у мові, тому що вони мають прийняти рішення. Особисто мені все одно, що має перевагу; Я скористався дужками, щоб переконатися, що я отримую очікуваний результат. Справа не в тому, чому вона робить те, що робить; мова йде про можливість зрозуміти, що робить код, коли ти повертаєшся до нього тижнями, місяцями чи роками пізніше.
Джефф Сівер

25
@Jeff: Це не правильно. Для цього рішення існує математична основа - це називається булева алгебра .
EFraim

4
@TheSteve: коротке замикання не впливає на результат вираження. Це впливає лише на побічні ефекти.
EFraim

8
Той факт, що вам навіть доводиться це розглядати, означає, що вам не слід покладатися на те, що наступний хлопець знає, якщо є питання, що комусь в офісі, можливо, доведеться витратити 3 секунди на це, тоді вкладіть .5 секунд, щоб додати а (і а)
Білл К

34
Дозвольте подивитися, чи я все зрозумів. Ваш колега має переконання щодо мови. Це переконання суперечить як специфікації, так і реалізації. Ваша претензія відповідає специфікації та реалізації. То чому саме ВИ намагаєтесь побудувати доказ? Тягар доказування покладається на людину, яка має шалену віру, а не на людину, яка має розумну віру. Я б більше не витрачав на це час; якщо вони хочуть витратити свій час, намагаючись довести щось фальшиве, нехай.
Ерік Ліпперт,

Відповіді:


116

Змінити перше false на true. Я знаю, що це здається дурним (true || true), але це підтверджує вашу думку.

bool result = true || true && false;   // --> true 
     result = (true || true) && false; // --> false
     result = true || (true && false); // --> true

13
Коротке замикання виникає лише тоді, коли відомий результат булевого виразу; коротке замикання не може змінити результат булевого виразу.
Капітан Сегфолт

5
@ Джеймс, ні, не було б .. Якби || мав вищий пріоритет, тоді вираз був би еквівалентним (true || true) && false => False, not true, оскільки після обчислення {true || true) як правда, те, що залишилося б, це true && false, що НЕ створювало короткого замикання
Charles Bretana

6
@James, Ні, якщо || мав вищий пріоритет, clr оцінив би це як (true або true) && false. тому спочатку це оцінить (true || true). Так, у цьому виразі так відбувається коротке замикання, оскільки для виразу АБО, якщо перша частина відповідає дійсності, немає необхідності оцінювати другу частину. Отже, це оцінює як істину. Тепер ми маємо true && false. Для операцій && коротке замикання відбувається лише в тому випадку, якщо перша частина - FALSE, що в даному випадку це не так, тому обидві частини повинні бути істинними, щоб A&& B еволюціонував як істинний. Тож воно оцінює обидві частини і придумує хибне
Чарльз Бретана

14
Чи не могли б ми просто зупинити все це безглуздя, яке, схоже, повторюється з приводу нудоти ?! Повторіть зі мною: КОРОТКО-КОЛІС НЕ ЗМІНЮЄ РЕЗУЛЬТАТ Коротке замикання застосовується лише тоді, коли результат вже відомий. КОРОТКО-КОЛІВНІ ТІЛЬКИ ВПЛИВАЮТЬ ПОБОЧНІ ЕФЕКТИ
EFraim

9
@comecme Це не результат короткого замикання, а зміна порядку роботи. Оператор & має вищий пріоритет, ніж | оператор, тому перший вираз поводився б як true | (false & false). Це оцінить як істинне, тому що false & false = falseтоді false | true = true. Однак, | Оператор має вищий пріоритет, ніж оператор &&, тому другий вираз поводиться як (true | false) && false. Це означало б значення false, бо true | false = trueтоді true && false = false.
Abion47

11

Якщо ви дійсно хочете збити його, спробуйте:

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

Буде надруковано:

True
False
False
-----
False

Редагувати:

У відповідь на коментар:

У C # |- це логічний оператор, який виконує ту ж логічну логіку, що і ||, але не замикає. Також у C # |оператор має вищий пріоритет, ніж обидва ||та &&.

Роздрукувавши значення, ви можете побачити, що якби я використовував типовий ||оператор, Trueдрукувався б лише перший , а потім результат виразу, який також був би True.

Але через вищий пріоритет |, true | falseспочатку оцінюється (в результаті true), а потім цей результат &&редагується, falseщоб отримати false.

Я не намагався показати порядок оцінки, лише той факт, що права половина |періоду оцінки, коли це зазвичай не було :)


1
a. Навіщо змішувати логічний та побітовий оператори? b. Чому ви наполягаєте на його друкуванні? Яке відношення до цього має порядок оцінки?
EFraim

2
Відповідь на відповідь: | все ще є двійковою. Просто для bool він виконує бажану операцію - як це робиться в C ++. Щоб пояснити це, MS документує це як логічне для bool's. Але ІМХО це просто каламутна вода.
EFraim

1
Це була б кумедна витівка. :)
Джеймс

1
Таким чином, якщо ви зміните ||до |і залишити &&, то результат виразу змінюється від істинного на хибне? Таким чином, ви зазвичай або використовуєте |разом &, або використовуєте ||разом з &&.
comecme

6

Хіба це не допоможе вам отримати те, що ви шукаєте? А може мені чогось не вистачає ...

bool result = true || false && false;

Це розрізняє &&, що мають вищий пріоритет, та || має вищий пріоритет, але не розрізняє || мають вищий пріоритет та && та || мають рівний пріоритет. Пам'ятайте, що якщо оператори мають однакове перевагу, вони просто оцінюються зліва направо.
Тайлер Макгенрі

1
Слід сказати, що це справді працює як доказ для C # (або для будь-якої звичайної мови), оскільки фактичний результат, який ви отримуєте, однозначний. Це просто не загальний метод для визначення відносного пріоритету на випадок, якщо ви стикаєтесь з езотеричною мовою, яка навмисно суперечить булевій алгебрі.
Тайлер Макхенрі,

5

Ви не доводите це кодом, а логікою. І - булеве множення, тоді як АБ - булеве додавання. Тепер який з них має вищий пріоритет?


10
У деяких мовах цього не робить жоден (наприклад, Smalltalk). Аналогії можуть бути оманливими.
Павло Мінаєв

11
Я не знаю про іншого виборця, але я проголосував, бо це не має нічого спільного з питанням. Буває, що це збігається ... але кожен може розробити мову Foo #, де це не відповідає дійсності; як тоді працював би ваш " доказ з логікою"? Це може пояснити, чому було обрано цей пріоритет, але це не допомагає встановити, що встановлений мною компілятор насправді поводиться саме так.
Роман Старков

2
@romkyns: Це все пов’язано з мовою. Правила С і С ++ походять від законів алгебри. Ось чому + має менший пріоритет, ніж *. Ви можете сперечатися з усім, що хочете, але ви одночасно помиляєтесь і неприємні. Ваш компілятор поводиться відповідно до специфікації мови, і специфікація мови має основу в алгебрі, QED
EFraim

3
QED? Чи знаєте ви, що означає щось доводити ? Мова може бути призначена для дотримання законів алгебри, але як ви докажете, що між цим наміром та величезною кількістю інженерних зусиль ніхто не плутав і випадково не порушував її або невірно прочитав специфікацію при впровадженні правил пріоритету? (малоймовірно, але не неможливо)
Роман Старков

3
Я думаю, що викладене Вами аргумент є дійсним, це просто те, що воно не кваліфікується як "доказ", де доказ - це щось набагато суворіше, ніж просто пояснення того, як і чому мовні дизайнери вирішили щось робити. "Вони базувались на алгебрі, тому вона обов'язково працює як алгебра" - це не суворий доказ (і насправді сказати це логічно невірно).
Dave Cousineau

1

хибний || правда-правда

Урожайність: правда

false && true || правда

Урожайність: правда


Перше твердження поверне true, незалежно від того, в якому порядку ви виконуєте операції. Друге поверне false, якщо || оцінюється першим. Оскільки воно повертає true, або && оцінюється спочатку, або вони мають однаковий пріоритет і оцінюються зліва направо. Третє твердження true || true && false(яке також повертає true) може бути істинним, лише якщо && оцінюється спочатку.
CodeHxr

-5

Ви не можете просто показати кінцевий результат, коли ваші логічні вирази перебувають у короткому замиканні. Ось фрагмент, який вирішує вашу справу.

Він покладається на впровадження & та | оператори, що використовуються && та ||, як зазначено в MSDN 7.11 Умовні логічні оператори

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

Результат повинен показувати, що && оцінюється спочатку перед ||.

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

Для додаткового задоволення спробуйте з результатом = t || t && f і подивіться, що відбувається з коротким замиканням.


6
Коротке замикання не має нічого спільного з результатом вираження. Чи можемо ми просто пережити це?
EFraim
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.