2009-10-08 3 views
9

Я использовал один амперсанд (&) в C# для обозначения «проверьте второй условный оператор, даже если первый false».Каково второе значение одного амперсанда в C#?

Но следующее кажется другой смысл из & вообще, может кто-нибудь объяснить, как 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); 
+0

Если вы думаете об этом заявлении ... Это неэффективно. – Min

+0

Я получил это от этого вопроса http://stackoverflow.com/questions/1537528/how-to-convert-system-linq-enumerable-wherelistiteratorint-to-listint/1537568#1537568, в котором было указано, что & -образный вариант Быстрее. –

ответ

31

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

Думайте в двоичной системе:

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

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

+0

В C++ вы можете использовать & с значениями bool *, потому что * bool автоматически переключается на ноль или один (и обратно) - как только вы оптимизируете касты, вы остаетесь с чем-то эквивалентным &&, но без оценки короткого замыкания (так что вы гарантируете, что побочные эффекты правого подвыражения происходят). Я предполагаю, что это относится к C# и Java, но не помню точно ATM. – Steve314

+0

@Steve: Согласно вопросу OP, они уже знают, что это поведение существует как способ не закорачивать логическую логику. –

+0

@Jeff - но он не знал, что такое оператор, поэтому не знал, почему это сработало для этого.Просто пытаюсь связать существующие знания с новыми, пояснив, что поведение bool Эдвард знает, что вы ошибаетесь из поразрядного поведения, которое вы объяснили, и поведение bcl <-> int casting. – Steve314

16

Here:

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

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

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

6

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

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

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

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

4

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

Например, если х 0110 и у 1010, то побитовое И результатов х и у (х & у) в 0010.

7

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

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

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

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

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

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

+0

Спасибо за * на самом деле * объяснив это – BritishDeveloper

+1

Обратите внимание, что в C# оператор '&&' может использоваться только между двумя 'bool', поэтому запрос, если первый операнд равен нулю, не имеет смысла (в C# a' bool' может быть только 'false' или' true', никогда не число), и особенно '5 && 6' не допускается. Но описание релевантно для других языков. –

+0

Упс, я плыл с C# на C/C++. – Jay

Смежные вопросы