Каково второе значение одного амперсанда в С#?
Я использовал одиночный амперсанд (&) в С# для обозначения "проверить условный оператор второй, даже если первый 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
. В любом случае он продолжает оценивать выражение.
То есть между &
и &&
есть два принципиальных различия:
-
&
работает по битам, в то время как &&
рассматривает только ноль и ненулевое значение и всегда возвращает 0 или 1. Таким образом, 5 & 6
(двоичные 101 & 110
) дают 4 (двоичные 100
), в то время как 5 && 6
дают 1 (true
).
-
&&
"Короткие замыкания". Если первое значение равно нулю, оно не оценивает второе значение. &
нет такого правила. Это важно по нескольким причинам:
- Если второе значение имеет какие-либо побочные эффекты, то с
&
эти побочные эффекты всегда случаются, тогда как с &&
они не имеют. Таким образом, x & (y++)
всегда будет увеличивать y
, тогда как x && (y++)
будет увеличивать y
только если x
не равно нулю. Это становится более важным - и, возможно, более тонким - если второй операнд является вызовом функции. - Первое значение может проверять что-то, что определяет, что второе значение недопустимо. Например,
x!=NULL && x->foo==3
. С &
, когда x
равен null
, это может привести к бомбардировке с ошибками сегмента или эквивалентными. - Наконец, могут быть важные улучшения производительности. Например,
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
Побитовый оператор И.