Подтвердить что ты не робот

Ясное, непрофессиональное объяснение разницы между | и || в С#?

Хорошо, поэтому я читал об этом несколько раз, но мне еще предстоит услышать четкий, понятный (и запоминающийся) способ узнать разницу между:

if (x | y)

и

if (x || y)

.. в контексте С#. Может кто-нибудь, пожалуйста, помогите мне узнать эту основную истину и как С# конкретно относится к ним по-разному (потому что они, похоже, делают то же самое). Если разница между данной частью кода между ними не имеет значения, что я должен по умолчанию использовать как наилучшую?

4b9b3361

Ответ 1

|| - логический или оператор. См. здесь. Он оценивает значение true, если хотя бы один из операндов истинен. Вы можете использовать его только с булевыми операндами; это ошибка, чтобы использовать его с целыми операндами.

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

| является оператором or. См. здесь. Если применяется к булевым типам, он оценивается как true, если хотя бы один из операндов истинен. Если применяется к целым типам, он вычисляет другое число. Это число имеет каждый бит, установленный в 1, если хотя бы один из операндов имеет соответствующий бит.

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

Для булевых операндов a || b идентичен a | b, за единственным исключением, что b не оценивается, если a - true. По этой причине || называется "короткозамкнутым".

Если разница между данной единицей кода между ними не имеет значения, что я должен по умолчанию использовать как наилучшую?

Как уже отмечалось, разница не является несущественной, поэтому этот вопрос частично спорен. Что касается "лучшей практики", то нет никого: вы просто используете любой оператор, который будет правильным. В общем, люди предпочитают || над | для булевых операндов, так как вы можете быть уверены, что он не будет создавать ненужные побочные эффекты.

Ответ 2

При использовании с булевыми операндами оператор | является логическим оператором так же, как ||, но разница в том, что оператор || выполняет оценку короткого замыкания, а оператор | не выполняет.

Это означает, что второй операнд всегда оценивается с помощью оператора |, но с помощью оператора || второй операнд оценивается только в том случае, если первый операнд имеет значение false.

Результат выражения всегда один и тот же для обоих оперантов, но если оценка второго операнда вызывает что-то другое, это гарантируется, только если вы используете оператор |.

Пример:

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.

Оценка короткого замыкания оператора || может использоваться для записи более короткого кода, поскольку второй операнд оценивается только в том случае, если первый операнд истинен. Вместо того, чтобы писать вот так:

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

Вы можете написать вот так:

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

Второй операнд оценивается только в том случае, если первый из них является ложным, поэтому вы знаете, что вы можете безопасно использовать ссылку на строку во втором операнде, поскольку она не может быть нулевой, если второй операнд оценивается.

В большинстве случаев вам нужно использовать оператор ||, а не оператор |. Если первый операнд является ложным, нет необходимости оценивать второй операнд, чтобы получить результат. Кроме того, многие люди (очевидно) не знают, что вы можете использовать оператор | с булевыми операндами, поэтому они будут запутаны, увидев, что он используется таким образом в коде.

Ответ 3

Они не совпадают. Один - побитовое ИЛИ, а одно - логическое ИЛИ.

X || Y, является логическим или означает то же, что и "X или Y", и применяется к значениям bool. Он используется в условных выражениях или тестах. X и Y в этом случае могут быть заменены любым выражением, которое оценивается как bool. Пример:

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

Условие присваивает значение true, если выполняется одно из двух условий. Если первое условие истинно (если файл существует), то второе условие не обязательно и не будет оцениваться.

Единственный канал (|) является побитовым ИЛИ. Чтобы узнать, что это значит, вы должны понимать, как номера хранятся на компьютере. Предположим, что у вас есть 16-битное количество (Int16), которое содержит значение 15. Оно фактически хранится как 0x000F (в шестнадцатеричном формате), которое совпадает с 0000 0000 0000 1111 в двоичном формате. Побитовое ИЛИ принимает две величины и ИЛИ каждая пара соответствующих битов вместе, так что, если бит равен 1 в любом количестве, в результате получается 1. Следовательно, если a = 0101 0101 0101 0101 (который оценивается в 0x5555 в гексагоне) и b = 1010 1010 1010 1010 (что равно 0xAAAA), тогда a | b = 1111 1111 1111 1111 = 0xFFFF.

Вы можете использовать побитовое ИЛИ (однотрубное) в С# для проверки того, включен ли один или несколько определенных битов. Вы можете сделать это, если у вас есть, допустим, 12 логических или двоичных значений для тестирования, и все они независимы. Предположим, у вас есть база данных студентов. Набор независимых булевых элементов может быть таким, как: мужчина/женщина, домашний/на кампусе, текущий/не текущий, зарегистрированный/не зарегистрированный и т.д. Вместо того, чтобы хранить логическое поле для каждого из этих значений, вы можете хранить всего лишь один бит для каждого. Мужчина/женщина может быть бит 1. зарегистрированный/не может быть бит 2.

Затем вы можете использовать

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

в качестве теста, чтобы убедиться, что бит не включен, кроме бита "студент - мужчина", который игнорируется. А? Ну, побитовое ИЛИ возвращает 1 для каждого бита, который включен в любом номере. Если результат побитового ИЛИ выше = 0x0001, это означает, что в битовом поле нет бит, кроме, может быть, первого бита (0x0001), но вы не можете точно сказать, включен ли первый бит, потому что он маскируется.

Существует соответствующий && и &, который является логическим И и побитовым И. Они имеют аналогичное поведение.

Вы можете использовать

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

чтобы увидеть, включен ли первый бит в поле бит.

EDIT: Я не могу поверить, что я проголосовал за это!

Ответ 4

Хорошие ответы, но позвольте мне добавить, что правые выражения для || не оцениваются, если левое выражение true. Помните об этом в тех случаях, когда условия оценки: a) интенсивность работы или b) создают побочные эффекты (редко).

Ответ 5

В отличие от того, что говорит большинство ответов, значение не совсем то же, что и в С++.

Для любых двух выражений A и B, вычисляющих booleans, A || B и A | B делает почти то же самое.

A | B оценивает как A, так и B, и если один из них оценивает значение true, результат будет истинным.

A || B делает почти то же самое, за исключением того, что он сначала оценивает A, а затем оценивает B только в том случае, если это необходимо. Поскольку все выражение истинно, если либо A, либо B истинно, B вообще не нужно тестировать, если A истинно. Итак, || коротких замыканий и пропускает оценку второго операнда, когда это возможно, где | оператор всегда будет оценивать оба.

The | оператор часто не используется, и часто это не изменит ситуацию. Единственным распространенным случаем я могу подумать, где это будет иметь значение:

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

}

Это работает, потому что функция члена DoStuff() никогда не вызывается, если левый тест выходит из строя. То есть, если foo имеет значение NULL, мы не называем DoStuff на нем. (что даст нам исключение NullReferenceException).

Если бы мы использовали | оператор, DoStuff() будет вызван независимо от того, был ли foo пустым или нет.

В целых числах только | оператор определен и побитовое ИЛИ, как описывают другие ответы. || оператор не определен для целых типов, хотя, поэтому трудно их перепутать в С#.

Ответ 6

| является побитовым оператором OR (числовым, целочисленным). он работает, преобразовывая числа в двоичные и делая OR для каждой из соответствующих цифр. то снова цифры уже представлены в двоичном виде на компьютере, поэтому такое преобразование действительно не выполняется во время выполнения;)

|| является логическим оператором OR (логическим). он работает только с истинными и ложными значениями.

Ответ 7

Следующее будет работать в C/С++, потому что у него нет поддержки для булевых классов в первом классе, он обрабатывает каждое выражение с помощью "on" бит на них как true, иначе false. На самом деле следующий код не будет работать на С# или Java, если x и y имеют числовые типы.

if (x | y) 

Таким образом, явная версия кода выше:

if ( (x | y) != 0)

В C любое выражение, имеющее бит "on" на них, приводит к истинному

int я = 8;

if (i)//действительный в C, приводит к истинному

int joy = -10;

if (joy)//vaild в C, приводит к true

Теперь вернемся к С#

Если x и y имеют числовой тип, ваш код: , если (x | y) не будет работать. Вы пытались скомпилировать его? Это не сработает

Но для вашего кода, который я мог бы считать x и y, имеет логические типы, поэтому он будет работать, поэтому разница между | и || для булевых типов || короткозамкнутый, | не является. Вывод следующего:

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

является:

HeyJudeGet
Yes
HeyBack

Джуд не будет дважды напечатан, || является булевым оператором, многие логические операторы с C-производными являются short-circuited, булевы выражения более эффективны, если они закорочены.

Что касается терминов непрофессионала, когда вы говорите короткое замыкание, например, в || (или оператор), если первое выражение уже верно, нет необходимости оценивать второе выражение. Пример: if (answer == 'y' || answer == 'Y'), если пользователь нажимает маленький y, программе не нужно оценивать второе выражение (ответ == 'Y'). Это короткое замыкание.

На моем примере кода выше X истинно, поэтому Y на || оператор не будет оцениваться дальше, поэтому нет второго выхода "Джуд".

Не используйте этот код в С#, даже если X и Y имеют логические типы: if (x | y). Не работает.

Ответ 8

Первый побитовый оператор работает с двумя численными значениями и приводит к третьему.

Если у вас есть двоичные переменные

a = 0001001b;
b = 1000010b;

то

a | b == 1001011b;

То есть, бит в результате равен 1, если он также равен 1 в любом из операндов. (Мой пример использует 8-битные номера для большей ясности)

"double pipe" ||, является логическим оператором OR, который принимает два булевых значения и приводит к третьему.

Ответ 9

Не вникая в детали каким-либо образом, форму или форму, здесь настоящая версия непрофессионала.

Подумайте о "|" как прямой "или" по-английски "; думать о" || "как" или еще" на английском языке.

Аналогично думайте о & как "и" на английском; подумайте о "& & "как" а также" на английском языке.

Если вы читаете выражение для себя, используя эти термины, они часто имеют больше смысла.

Ответ 10

Настоятельно рекомендуем читать эту статью из Dotnet Mob

Для логической операции OR, если любой из ее операндов оценивается как true, тогда целое выражение оценивается как true

это то, что || Оператор делает - он пропускает оставшуюся оценку, когда обнаружил истину. Пока | Оператор оценивает его полные операнды для оценки значения целого выражения.

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

Лучше использовать короткоколебаемую версию логического оператора. Является ли это OR (||) или AND (& &) Operator.


Рассмотрим следующий фрагмент кода
int i=0;
if(false||(++i<10))//Now i=1
{
//Some Operations
}
if(true||(++i<10))//i remains same, ie 1
{}

Этот эффект называется побочным эффектом, фактически видимым в правой части выражения в коротких замыкающих логических операциях

Ссылка: Оценка короткого замыкания на С#

Ответ 11

Хотя это уже было сказано и правильно ответили, я подумал, что добавлю настоящего непрофессионала ответ, потому что много времени, что я чувствую себя на этом сайте:). Плюс я добавлю пример и vs. && так как это одно и то же понятие

| vs ||

В основном вы склонны использовать || когда вы только хотите оценить вторую часть, если первая часть ЛОЖЬ. Итак:

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

совпадает с

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

Это может быть способ сохранить время обработки. Если func2() потребовалось много времени для обработки, вы бы не захотели этого сделать, если func1() уже был true.

& vs &&

В случае и vs. && это аналогичная ситуация, когда вы оцениваете только вторую часть, если первая часть ИСТИНА. Например:

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

совпадает с

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

Это может быть необходимо, так как func2() может зависеть от func1(), сначала являющегося истинным. Если вы использовали и и func1() получили значение false, и всегда запускали func2(), что могло бы вызвать ошибку времени выполнения.

Джефф Лэймен