Difference between ! and ~ in c#

When I first leared how to write programs, I used C. (very basic command line applications) In both languages you use the ! - operator normally like this:

    if(!true){
       //false..
}

I wanted to do some bit-masking in c# and i wondered about the '~' operator.

Now i'm a bit confused because in my own understanding ! and ~ should do the same thing.

This works in c#:

int i = ~0xffffffff; // i = 0
bool j = !true; // j = false

This doesn't: (But it does work in c and does exactly what i expected)

int i = !0xffffffff; // i = 0

So what is the diffrence between ~ and ! and why did they separate them?

Answers


C# made the decision to completely separate integer operations from boolean operations. You cannot for example do if(x & 4) you must do if((x & 4) != 0) to explicitly move from integers to booleans.

This is in line with over 4 decades of experience with C and its predecessors in which people have often made mistakes with it such as &ing two values that had a truth-value of true and getting false because while they where both non-zero they had no non-zero bits in common.

C and C++ both introduced a bool type late in their history to add a more explicit difference between integers that represent either numbers or bit-patterns, and values where we only care about truth-values, but had to be compatible with older code. C# had the luxury of being even more explicit.

With that in mind, C#'s ! and ~ are exactly the same as in C, except that some things no longer make sense:

In C ! negates truth value. It turns 0 (false) into 1 (true) and everything non-zero (true) into 0 (false). In C# that only makes sense with bool, not with int.

In C ~ produces the one's-complement; It produces a value where every 1 bit is turned to 0 and every 0 bit is turned to 1 (e.g. 0xFFFFFFFF becomes 0, 0xF0F0F0F0 becomes 0x0F0F0F0F and so on). In C# that makes sense with int, but not with bool.

If you want to do the equivalent of !someInteger in C#, do someInteger == 0.

Edit:

It's worth noting that there is sometimes some confusion caused by the operators being split into "bitwise" ('&', '|' and '~') and "boolean" ('&&', '||' and '!'). This distinction is not quite correct.

Now, the last three do indeed only make sense in boolean contexts, and so with C# having a stricter separation between boolean and integer values, they are no longer applied to integers.

'~' does indeed not make sense in boolean contexts ('~x' where 'x' is true will produce an 'x' that is still true, 4294967294 times out of 4294967295), and so with C# it's no longer applied to bools.

'&' and '|' retain a boolean use though. In the case where 'A()' and 'B()' each return a bool, then while A() && B() will only call B() if A() is false (that is, it "short-circuits"), A() & B() will always call both methods, before doing the ∧ Boolean arithmetic. This tends to be rare because:

  1. Most of the time calling B() is just a waste of time, and short-circuiting can give us a performance boost ranging from massive (if B() is expensive) through to made-no-difference-but-we-didn't-lose-anything-anyway, so it's the habit to be in. (But consider that if B() is very cheap the cost of calling it anyway might be cheaper than the branch, especially if mispredicted, see comments below).

  2. Sometimes && is compulsory such as in x != null && x.Length != 0 where not short-circuiting would throw an exception on the second argument.

  3. If it's that important to make sure both methods were called, then it's better coding to do this in separate statements, to make that clear to other developers (or yourself when you come back later).

But if we're going to talk about the difference between operators with boolean and integer arguments, we should include the boolean use of | and &, because they do come up (sometimes through typos!), and they can cause confusion if people are falsely separating "bitwise operators" and "boolean operators" and forgetting that there are two symbols that are used as both.


! is a boolean invert, it inverts a value from true to false and vice versa. http://msdn.microsoft.com/en-us/library/f2kd6eb2.aspx

~ is a bitwise invert, it inverts every bit of an integral value, like int i. http://msdn.microsoft.com/en-us/library/d2bd4x66.aspx

see http://msdn.microsoft.com/en-us/library/6a71f45d.aspx for full guide on all operators.

The reason why ! and ~ are separate is because they do different things.


~The bitwise NOT operator is a unary operator, as it includes single operand. Unlike the other bitwise operators, the bitwise version does not use the same symbol as the similar Boolean operator. To achieve a one's complement, the tilde character (~) is positioned to the left of the value to modify.

byte valueToComplement = 187;                  // 10111011  
byte complement = (byte) ~valueToComplement;   // Result = 68

! - is a boolean invert which can be either true or false.


Need Your Help

Yii2 save related records in single save call in single transaction

activerecord transactions yii2

In yii2 how can i save multiple related records into db into single save call and single transaction.

NSOperationQueue serial FIFO queue

ios objective-c nsoperationqueue fifo serial-processing

Is it possible to use an NSoperationQueue object as a serial FIFO queue by setting its maxConcurrentOperationCount to 1?