Ответ 1
С# решило полностью отделить целые операции от булевых операций. Вы не можете, например, сделать if(x & 4)
, вы должны сделать if((x & 4) != 0)
, чтобы явно перемещаться из целых чисел в booleans.
Это соответствует более чем 4-летнему опыту с C и его предшественниками, в которых люди часто совершали с ним ошибки, такие как и два значения, которые имели значение истинности true
и получали false
, потому что в то время как они, где оба отличны от нуля, не имели ненулевых битов.
C и С++ представили тип bool
в конце своей истории, чтобы добавить более явное различие между целыми числами, которые представляют либо числа, либо битовые шаблоны, и значения, где мы только заботимся об истинных значениях, но должны быть совместимы с более старым кодом. У С# была роскошь быть еще более явной.
Имея это в виду, С# !
и ~
точно такие же, как в C, за исключением того, что некоторые вещи уже не имеют смысла:
В C !
отрицает значение истины. Он превращает 0 (false) в 1 (true) и все ненулевые (true) в 0 (false). В С#, который имеет смысл только с bool
, а не с int
.
В C ~
получается одно-дополнение; Он генерирует значение, когда каждый 1 бит поворачивается на 0 и каждый 0 бит поворачивается на 1 (например, 0xFFFFFFFF становится 0, 0xF0F0F0F0 становится 0x0F0F0F0F и т.д.). В С#, который имеет смысл с int
, но не с bool
.
Если вы хотите сделать эквивалент !someInteger
в С#, выполните someInteger == 0
.
Edit:
Стоит отметить, что иногда возникает некоторая путаница, вызванная разбиением операторов на "поразрядные" ( "&", "|" и "~" ) и "boolean" ('& &', '| | 'и'! '). Это различие не совсем корректно.
Теперь последние три действительно имеют смысл в булевых контекстах, и поэтому, когда С# имеет более строгое разделение между логическими и целочисленными значениями, они больше не применяются к целым числам.
'~' действительно не имеет смысла в булевых контекстах ( "~ x", где "x" - true, будет генерировать "x", который по-прежнему верен, 4294967294 раза из 4294967295), и поэтому с С# он больше не применяется к bools.
'&' и '|' сохраняйте булевское использование. В случае, когда 'A()' и 'B()' возвращают a bool
, тогда, когда A() && B()
будет вызывать только B()
, если A()
является ложным (то есть, это "короткие замыкания" ), A() & B()
всегда будет вызывать оба метода, прежде чем выполнять арифметику ∧
Boolean. Это, как правило, редко, потому что:
-
В большинстве случаев вызов
B()
- это просто пустая трата времени, и короткое замыкание может дать нам повышение производительности, начиная с массивного (еслиB()
дорого) до того, но мы все-таки ничего не теряли, так что привычка быть в нем. (Но считайте, что еслиB()
очень дешево, стоимость его вызова в любом случае может быть дешевле, чем отрасль, особенно если это неверно предсказано, см. комментарии ниже). -
Иногда
&&
является обязательным, например, вx != null && x.Length != 0
, где не короткое замыкание будет вызывать исключение во втором аргументе. -
Если это важно, чтобы удостовериться, что оба метода были вызваны, то лучше кодировать это в отдельных инструкциях, чтобы сделать это понятным для других разработчиков (или самостоятельно, когда вы вернетесь позже).
Но если мы поговорим о различии между операторами с логическими и целочисленными аргументами, мы должны включить логическое использование |
и &
, потому что они появляются (иногда через опечатки!) и они могут вызвать путаницу, если люди ложно отделяют "побитовые операторы" и "логические операторы" и забывают, что есть два символа, которые используются как оба.