Каково второе значение одного амперсанда в С#?

Я использовал одиночный амперсанд (&) в С# для обозначения "проверить условный оператор второй, даже если первый false".

Но следующее, кажется, вообще различное значение &, может ли кто-нибудь объяснить, как i & 1 работает в следующем примере?

List<int> scores = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8 };
var evenScores = scores.Where(i => i % 2 == 0);
var evenScores2 = scores.Where(i => (i & 1) == 0);

Ответ 1

Один и является "Побитовым оператором И", как сказал dove. Я рассматриваю вторую часть вопроса: "Почему это работает?"

Подумайте в двоичном формате:

 000 = 0
 001 = 1
 010 = 2
 011 = 3
 100 = 4
 101 = 5
 110 = 6
 111 = 7
 and so on

Обратите внимание, что все четные числа заканчиваются на 0; так что если бит последнего бит бит проверяет на 1 возвращает ноль (что означает "не соответствует" ), его четное число;

Ответ 2

Здесь:

Унарный & operator возвращает адрес своего операнда (требуется unsafe контекст).

Двоичные & operators предопределены для интегральных типов и bool. Для интегральных типов & вычисляет логический побитовый AND его операндов. Для операндов bool & вычисляет логические AND своих операндов; то есть результат верен тогда и только тогда, когда оба его операнда верны.

& operator оценивает оба оператора независимо от первого значения.

Ответ 3

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

Как уже было сказано, & является побитовым И. && - это логическое И. & выполняет операцию И над своими операндами побитово, и в целом выполняет функции точно так же, как + или * или любой арифметический оператор. && более сложный. Он сравнивает каждый из своих операндов с нулем. Если первый операнд равен нулю, он принимает значение false и замыкает остальную часть выражения, т.е. Не оценивает оставшиеся операнды. Если первое значение не равно нулю, оно проверяет второе значение. Если это ноль, он принимает значение false, в противном случае он принимает значение true. В любом случае он продолжает оценивать выражение.

То есть между & и && есть два принципиальных различия:

  1. & работает по битам, в то время как && рассматривает только ноль и ненулевое значение и всегда возвращает 0 или 1. Таким образом, 5 & 6 (двоичные 101 & 110) дают 4 (двоичные 100), в то время как 5 && 6 дают 1 (true).

  2. && "Короткие замыкания". Если первое значение равно нулю, оно не оценивает второе значение. & нет такого правила. Это важно по нескольким причинам:

    1. Если второе значение имеет какие-либо побочные эффекты, то с & эти побочные эффекты всегда случаются, тогда как с && они не имеют. Таким образом, x & (y++) всегда будет увеличивать y, тогда как x && (y++) будет увеличивать y только если x не равно нулю. Это становится более важным - и, возможно, более тонким - если второй операнд является вызовом функции.
    2. Первое значение может проверять что-то, что определяет, что второе значение недопустимо. Например, x!=NULL && x->foo==3. С &, когда x равен null, это может привести к бомбардировке с ошибками сегмента или эквивалентными.
    3. Наконец, могут быть важные улучшения производительности. Например, x!='A' && readTonsOfStuffFromDatabaseAndCalculateTotal(x). С & чтение будет происходить независимо, и, возможно, будет пустой тратой времени.

Вот почему мы почти всегда используем && для вещей, которые действительно являются логическими операциями, и ограничиваем использование & когда мы действительно хотим побитовую операцию. Но бывают случаи, когда вы не хотите, короткое замыкание произойдет, и в этом случае & может быть хорошим выбором. Но если вы используете его для работы "логически", будьте очень осторожны с операндами, которые могут иметь любые значения, кроме 0 или 1. 1 && 2 - это true, а 1 & 2 - это false.

Ответ 4

Для булевых типов вы упомянули, как это происходит.

Для целых типов это побитовый оператор "и".

Он может быть перегружен для других типов.

В основном выражение (i & 1) == 0 проверяет, установлен ли младший значащий бит i, что происходит только в том случае, если число нечетное.

Ответ 5

Амперсанд представляет собой поразрядную операцию И. Побитовый оператор возвращает результат сравнения между каждым соответствующим битом в двух операндах.

Например, если x равно 0110, а y равно 1010, то побитовое И из x и y (x и y) приводит к 0010.

Ответ 6

Побитовый оператор И.