枚举定义中的波浪号(〜)是多少?

时间:2008-12-22 21:36:08

标签: c# enums language-features enumeration

我总是感到惊讶的是,即使现在一直使用C#,我仍然设法找到我不知道的事情......

我已经尝试在网上搜索,但在搜索中使用“〜”对我来说效果不好,而且我在MSDN上也找不到任何东西(不是说它不存在)

我最近看到了这段代码,代字号(〜)是什么意思?

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

我看到它有点惊讶,所以我试图编译它,它起作用了......但我仍然不知道它意味着什么/做了什么。任何帮助?

10 个答案:

答案 0 :(得分:134)

〜是一元的补码运算符 - 它会翻转其操作数的位。

~0 = 0xFFFFFFFF = -1

用二进制补码算术~x == -x-1

〜运算符几乎可以在任何借用C语法的语言中找到,包括Objective-C / C ++ / C#/ Java / Javascript。

答案 1 :(得分:57)

我认为:

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

会更清楚一点。

答案 2 :(得分:21)

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的数字。

答案 3 :(得分:15)

它比

更好
All = Cash | Check | CreditCard

解决方案,因为如果您稍后再添加其他方法,请说:

PayPal = 8 ,

你已经完成了波浪号 - 全部,但必须用另一个改变全线。因此,以后它不易出错。

问候

答案 4 :(得分:10)

当您使用

时,请注意
All = Cash | Check | CreditCard

您有Cash | Check | CreditCard评估为All的额外好处,而不是包含所有值时不等于所有值的另一个值(-1)。 例如,如果在UI中使用三个复选框

[] Cash
[] Check
[] CreditCard

并对其值进行求和,用户全部选择它们,您会在结果枚举中看到All

答案 5 :(得分:9)

对于其他发现这个问题的人来说,我有一个快速的~示例来分享。如this Mono documentation中所述,执行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
}

请注意这个枚举与Sean Bright的答案相似吗?

我认为对我来说最重要的一点就是~与enum中的运算符相同,与正常的代码行相同。

答案 6 :(得分:5)

这是一个补充算子, 这是我经常提到的用于按位运算符的文章

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

msdn也在他们的枚举文章中使用它,证明它使用得更好

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

答案 7 :(得分:1)

我个人使用的替代方案,与@Sean Bright的答案相同,但对我来说看起来更好,就是这个:

[Flags]
public enum PurchaseMethod
{
    None = 0,
    Cash = 1,
    Check = 2,
    CreditCard = 4,
    PayPal = 8,
    BitCoin = 16,
    All = Cash + Check + CreditCard + PayPal + BitCoin
}

请注意这些数字的二进制特性(均为2的幂)如何使以下断言成立:(a + b + c) == (a | b | c)。恕我直言,+看起来更好。

答案 8 :(得分:1)

我做了一些实验〜并发现它可能有陷阱。考虑一下LINQPad的这个片段,它显示当所有值一起存储时,All enum值的行为不符合预期。

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 
}

答案 9 :(得分: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
}