Разница между ними! и ~ в c#
Когда я впервые узнал, как писать программы, я использовал C. (очень простые приложения командной строки) В обоих языках вы используете ! - оператор обычно выглядит так:
if(!true){
//false..
}
Я хотел сделать некоторую битовую маскировку в c#, и меня интересовал оператор'~'.
Теперь я немного запутался, потому что в моем собственном понимании ! и ~ должен сделать то же самое.
Это работает в c#:
int i = ~0xffffffff; // i = 0
bool j = !true; // j = false
Это не: (но он работает в c и делает именно то, что я ожидается)
int i = !0xffffffff; // i = 0
Так в чем же разница между ~ и ! и почему они их разделили?
3 ответа:
В C# принято решение полностью отделить целочисленных операций из логических операций. Вы не можете, например, сделать
Это согласуется с более чем 4-х десятилетним опытом работы с C и его предшественниками, в котором люди часто совершали ошибки с ним, такие как &ing два значения, которые имели значение истинностиif(x & 4)вы должны сделатьif((x & 4) != 0), чтобы явно перейти от целых чисел к логическим.trueи получениеfalse, потому что в то время как они оба ненулевые, у них не было ненулевых битов в общем.C и C++ оба ввели Тип
boolв конце своей истории, чтобы добавить более явное различие между целыми числами, которые представляют либо числа, либо битовые шаблоны, и значениями, где мы заботимся только о значениях истинности, но должны были быть совместимы с более старым кодом. Си# мог позволить себе роскошь быть еще более откровенным.Имея это в виду, C#S
!и~точно такие же, как в C, за исключением того, что некоторые вещи больше не имеют смысла:В C
!отрицает значение истинности. Он превращает 0 (false) в 1 (истина) и все ненулевое (истина) в 0 (ложь). В C# это имеет смысл только сbool, а не сint.В C
~производит дополнение единицы; оно производит значение, где каждый 1 бит превращается в 0, а каждый 0 бит превращается в 1 (например, 0xFFFFFFFF становится 0, 0xF0F0F0F0 становится 0x0F0F0F0F и так далее). В C# это имеет смысл сint, но не сbool.Если вы хотите сделать эквивалент
!someIntegerВ C#, сделайтеsomeInteger == 0.Правка:
Это стоит отметить. что иногда возникает некоторая путаница, вызванная разделением операторов на "побитовые" ( ' & ' , ' | 'и'~') и "булевы" ('&&', '||' и еще!"). Это различие не совсем верно.
Теперь последние три действительно имеют смысл только в булевых контекстах, и поэтому с C#, имеющим более строгое разделение между булевыми и целочисленными значениями, они больше не применяются к целым числам.'~ ' действительно не имеет смысла в булевых контекстах ('~x', где' x ' истинно, приведет к 'x', что по-прежнему верно, 4294967294 раза из 4294967295), и поэтому с C# он больше не применяется к bools.
'& ' и ' | ' сохраняют логическое использование, хотя. В случае, когда' A () 'и' B () ' каждый возвращает a
bool, то в то время какA() && B()будет вызывать толькоB(), ЕслиA()ложно (то есть это "короткие замыкания"),A() & B()всегда будет вызывать оба метода, прежде чем делать∧Булеву арифметику. Это имеет тенденцию быть редким, потому что:Но если мы собираемся говорить о разнице между операторами с булевыми и целочисленными аргументами, мы должны включить логическое использование
В большинстве случаев вызов
B()- это просто пустая трата времени., и короткое замыкание может дать нам повышение производительности, начиная от массивного (еслиB()дорого) до made-no-difference-but-we-didn't-lose-anything-anyway, так что это привычка. (Но учтите, что еслиB()очень дешево, то стоимость вызова его в любом случае может быть дешевле, чем ветка, особенно если она неправильно интерпретирована, см. комментарии ниже).Иногда
&&является обязательным, например, вx != null && x.Length != 0, где не короткое замыкание вызвало бы исключение на втором аргумент.Если это так важно, чтобы убедиться, что оба метода были вызваны, то лучше кодировать, чтобы сделать это в отдельных операторах, чтобы сделать это понятным для других разработчиков (или себя, когда вы вернетесь позже).
|и&, потому что они действительно возникают (иногда через опечатки!), и они могут вызвать путаницу. если люди ошибочно разделяют "побитовые операторы" и "булевы операторы" и забывают, что есть два символа, которые используются как оба.
!является булевым инвертом, он инвертирует значение изtrueвfalseи наоборот. http://msdn.microsoft.com/en-us/library/f2kd6eb2.aspx
~является побитовым инвертом, он инвертирует каждый бит интегрального значения, напримерint i. http://msdn.microsoft.com/en-us/library/d2bd4x66.aspxСм. http://msdn.microsoft.com/en-us/library/6a71f45d.aspx для полного руководства по всем операторам.
Причина, по которой
!и~разделены, заключается в том, что они делать разные вещи.
~побитовый оператор NOT является унарным оператором, так как он включает в себя один операнд. В отличие от других побитовых операторов, побитовая версия не использует тот же символ, что и аналогичный Булев оператор. Чтобы добиться дополнения единицы, символ тильды ( ~ ) расположен слева от значения, которое нужно изменить.byte valueToComplement = 187; // 10111011 byte complement = (byte) ~valueToComplement; // Result = 68
!- является логическим инвертом, который может быть либо истинным, либо ложным.