views:

3505

answers:

6

I'm always surprised that even after using C# for all this time now, I still manage to find things I didn't know about...

I've tried searching the internet for this, but using the "~" in a search isn't working for me so well and I didn't find anything on MSDN either (not to say it isn't there)

I saw this snippet of code recently, what does the tilde(~) mean?

/// <summary>
/// Enumerates the ways a customer may purchase goods.
/// </summary>
[Flags]
public enum PurchaseMethod
{   
    All = ~0,
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

I was a little surprised to see it so I tried to compile it, and it worked... but I still don't know what it means/does. Any help??

+9  A: 
public enum PurchaseMethod
{   
    All = ~0, // all bits of All are 1. the ~ operator just inverts bits
    None =  0,
    Cash =  1,
    Check =  2,
    CreditCard =  4
}

Because of two complement in C#, ~0 == -1, the number where all bits are 1 in the binary representation.

Johannes Schaub - litb
Looks like they are creating a bit flag for the payment method: 000 = None; 001 = Cash; 010 = Check; 100 = Credit Card; 111 = All
Dillie-O
It's not two's complement, that's invert all the bits and add one, so that the two's complement of 0 is still 0. The ~0 simply inverts all the bits or one's complement.
Bearddo
No, two's complement is simply inverting all the bits.
configurator
@configurator -- that's not correct. The ones complement is a simple inversion of bits.
Dave Markle
c# uses two complement to represent negative values. of course ~ is not two complement, but simply inverts all bits. i'm not sure where you got that from, Beardo
Johannes Schaub - litb
Just to clarify (for my sake). This doesn't do anything special in C# since -1 != 7, so basically you will have to end up doing [All = Cash | Check | CreditCard] ?
avgbody
yes, and also all other numbers you could add to it.
Johannes Schaub - litb
+28  A: 

~ is the unary one's complement operator -- it flips the bits of its operand.

~0 = 0xFFFFFFFF = -1

in two's complement arithmetic, ~x == -x-1

the ~ operator can be found in pretty much any language that borrowed syntax from C, including C++/C#/Java/Javascript.

Jimmy
That's cool. I didn't realise you could do that in an enum. Will definitely use in future
Orion Edwards
So it's the equivalent of All = Int32.MaxValue? Or UInt32.MaxValue?
Joel Mueller
All = (unsigned int)-1 == UInt32.MaxValue. Int32.MaxValue has no relevance.
Jimmy
I would imagine that All = Int32.MinValue?
Stevo3000
@Stevo3000: Int32.MinValue is 0xF0000000, which is not ~0 (it's actually ~Int32.MaxValue)
Jimmy
+2  A: 

It's a complement operator, Here is an article i often refer to for bitwise operators

http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx

Also msdn uses it in their enums article which demonstrates it use better

http://msdn.microsoft.com/en-us/library/cc138362.aspx

rizzle
+22  A: 

I'd think that:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    All = Cash | Check | CreditCard
 }

Would be a bit more clear.

Sean Bright
It certainly is. The only good effect of the unary is that if someone adds to the enumeration, All automagically includes it. Still, the benefit doesn't outweigh the lack of clarity.
ctacke
I don't see how that's more clear. It adds either redundancy or ambiguity: does "All" mean "exactly the set of these 3" or "everything in this enum"? If I add a new value, should I also add it to All? If I see somebody else *hasn't* added a new value to All, is that intentional? ~0 is explicit.
Ken
Personal preference aside, if the meaning of ~0 was as clear to the OP as it is to you and I, he never would have posed this question in the first place. I'm not sure what that says about the clarity of one approach versus the other.
Sean Bright
+5  A: 

Its better than the

All = Cash | Check | CreditCard

solution, because if you add another method later, say:

PayPal = 8 ,

you will be already done with the tilde-All, but have to change the all-line with the other. So its less error-prone later.

regards

blabla999
+4  A: 

Just a side note, when you use

All = Cash | Check | CreditCard

you have the added benefit that Cash | Check | CreditCard would evaluate to All and not to another value (-1) that is not equal to all while containing all values. For example, if you use three check boxes in the UI

[] Cash
[] Check
[] CreditCard

and sum their values, and the user selects them all, you would see All in the resulting enum.

configurator