什么是枚举定义中的代字号(〜)?
我总是感到惊讶,即使现在一直使用C#,我仍然设法find我不知道的事情…
我已经试过在网上search这个,但是在search中使用“〜”对我来说不是很好,我也没有在MSDN上find任何东西(不是说它不存在)
我最近看了这段代码,代字符(〜)是什么意思?
/// <summary> /// Enumerates the ways a customer may purchase goods. /// </summary> [Flags] public enum PurchaseMethod { All = ~0, None = 0, Cash = 1, Check = 2, CreditCard = 4 }
我有点惊讶地看到它,所以我试图编译它,它的工作…但我仍然不知道它是什么意思/做什么。 任何帮助?
〜是一元补码操作符 – 它翻转操作数的位。
~0 = 0xFFFFFFFF = -1
在二进制补码运算中, ~x == -x-1
〜运算符可以在几乎所有借用C语言的语言中find,包括Objective-C / C ++ / C#/ Java / Javascript。
我会认为:
[Flags] public enum PurchaseMethod { None = 0, Cash = 1, Check = 2, CreditCard = 4, All = Cash | Check | CreditCard }
会更清楚一点。
public enum PurchaseMethod { All = ~0, // all bits of All are 1. the ~ operator just inverts bits None = 0, Cash = 1, Check = 2, CreditCard = 4 }
由于C#中的两个补码, ~0 == -1
,在二进制表示中所有位都是1的数字。
它比
All = Cash | Check | CreditCard
解决scheme,因为如果您稍后添加其他方法,请说:
PayPal = 8 ,
你已经完成了波浪号 – 所有,但必须改变与其他的全线。 所以它后来不太容易出错。
问候
只是一个侧面说明,当你使用
All = Cash | Check | CreditCard
您有额外的好处, Cash | Check | CreditCard
Cash | Check | CreditCard
Cash | Check | CreditCard
将评估为All
而不是包含所有值的其他值(-1)不等于全部。 例如,如果在UI中使用三个checkbox
[] Cash [] Check [] CreditCard
并将它们的值相加,并且用户全部选中它们,则会在结果枚举中看到All
。
对于发现这个问题的其他人来说,我有一个快速的例子来分享。 在Mono文档中详细描述的实现paint方法的以下片段使用~
效果非常好:
PaintCells (clipBounds, DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground);
没有~
运算符,代码可能看起来像这样:
PaintCells (clipBounds, DataGridViewPaintParts.Background | DataGridViewPaintParts.Border | DataGridViewPaintParts.ContentBackground | DataGridViewPaintParts.ContentForeground | DataGridViewPaintParts.ErrorIcon | DataGridViewPaintParts.Focus);
…因为枚举看起来像这样:
public enum DataGridViewPaintParts { None = 0, Background = 1, Border = 2, ContentBackground = 4, ContentForeground = 8, ErrorIcon = 16, Focus = 32, SelectionBackground = 64, All = 127 // which is equal to Background | Border | ... | Focus }
注意这个枚举类似于肖恩·布莱特的答案?
我认为对我来说最重要的是, ~
是一个枚举中的运算符,就像它在一个正常的代码行中一样。
这是一个补充运算符,这是我经常提到的按位运算符的文章
http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx
另外MSDN在他们的枚举文章中使用它来certificate它更好用
我个人使用的替代方法,与@Sean Bright的回答相同,但对我来说更好,这是一个:
[Flags] public enum PurchaseMethod { None = 0, Cash = 1, Check = 2, CreditCard = 4, PayPal = 8, BitCoin = 16, All = Cash + Check + CreditCard + PayPal + BitCoin }
注意这些数字的二进制性质,它们都是两个幂,使得下面的断言是正确的: (a + b + c) == (a | b | c)
。 和恕我直言, +
看起来更好。
我已经做了一些试验,发现它可能有缺陷。 考虑这个LINQPad代码片断,它显示了当所有的值都在一起时,所有枚举值的行为并不像预期的那样。
void Main() { StatusFilterEnum x = StatusFilterEnum.Standard | StatusFilterEnum.Saved; bool isAll = (x & StatusFilterEnum.All) == StatusFilterEnum.All; //isAll is false but the naive user would expect true isAll.Dump(); } [Flags] public enum StatusFilterEnum { Standard =0, Saved =1, All = ~0 }
只是想添加,如果你使用[Flags]枚举,那么使用按位左移运算符可能会更方便,就像这样:
[Flags] enum SampleEnum { None = 0, // 0 First = 1 << 0, // 1b = 1d Second = 1 << 1, // 10b = 2d Third = 1 << 2, // 100b = 4d Fourth = 1 << 3, // 1000b = 8d All = ~0 // 11111111b }