声明按位枚举(标志) - 最近的c#语法为"DWORD风格"的怪癖?

drz*_*aus 1 c# syntax enums flags

背景:按位枚举对于"更易读"的比较和检查非常有用:即OpenFile(write | append).

我已经看到了几种在C#中声明按位枚举的方法,但是最近其中一种常见模式似乎不再返回唯一值,我想知道我是在宣告它是错还是有些东西已经改变了.我在谈论"DWORD"(十六进制?)样式(如下所示),在VS2012 RC中枚举时,值为1,2,3,4 ...而不是预期的逐位加倍.

其他人可以重现这个吗?我发布了用于验证的代码以及控制台输出; ComparisonsDword正如您可以通过"标记枚举,带有DWORD的显式值"的输出所看到的那样发生奇怪的行为.

没有标志,正常的枚举

/// <summary>
/// How to compare filter values; no underlying type declared, not flag
/// </summary>
public enum ComparisonsNotInt {
    [Description("x")]
    None
    ,
    [Description("!=")]
    NotEqual
    ,
    [Description("=")]
    Equal
    ,
    [Description(">")]
    GreaterThan
    ,
    [Description("<")]
    LessThan
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsNotFlag
Run Code Online (Sandbox Code Playgroud)

没有标志,底层类型= int

/// <summary>
/// How to compare filter values, not flag but underlying type declared
/// </summary>
public enum ComparisonsNotFlag : int {
    [Description("x")]
    None
    ,
    [Description("!=")]
    NotEqual
    ,
    [Description("=")]
    Equal
    ,
    [Description(">")]
    GreaterThan
    ,
    [Description("<")]
    LessThan
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsNotFlag
Run Code Online (Sandbox Code Playgroud)

标志,隐含价值

/// <summary>
/// How to compare filter values; values default to whatever .NET decides
/// </summary>
[Flags]
public enum ComparisonsImplicit : int {
    [Description("x")]
    None
    ,
    [Description("!=")]
    NotEqual
    ,
    [Description("=")]
    Equal
    ,
    [Description(">")]
    GreaterThan
    ,
    [Description("<")]
    LessThan
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsImplicit
Run Code Online (Sandbox Code Playgroud)

标志,显性值

/// <summary>
/// How to compare filter values; values explicitly defined with doubled numbers
/// </summary>
[Flags]
public enum ComparisonsExplicit : int {
    [Description("x")]
    None = 0
    ,
    [Description("!=")]
    NotEqual = 1
    ,
    [Description("=")]
    Equal = 2
    ,
    [Description(">")]
    GreaterThan = 4
    ,
    [Description("<")]
    LessThan = 8
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsExplicit
Run Code Online (Sandbox Code Playgroud)

标记,使用DWORD样式的显式值 注意:这是没有正确提供唯一值的内容,因此组合如GreaterThanOrEqual失败.

/// <summary>
/// How to compare filter values; values explicitly defined with DWORD style
/// </summary>
[Flags]
public enum ComparisonsDword : int {
    [Description("x")]
    None = 0x0
    ,
    [Description("!=")]
    NotEqual = 0x1
    ,
    [Description("=")]
    Equal = 0x2
    ,
    [Description(">")]
    GreaterThan = 0x3
    ,
    [Description("<")]
    LessThan = 0x4
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsDword
Run Code Online (Sandbox Code Playgroud)

标记,使用DWORD样式的显式值 注意:也是不合适的值,只是检查基础类型是否影响问题.

/// <summary>
/// How to compare filter values; values explicitly defined with DWORD style
/// </summary>
[Flags]
public enum ComparisonsDwordNotInt {
    [Description("x")]
    None = 0x0
    ,
    [Description("!=")]
    NotEqual = 0x1
    ,
    [Description("=")]
    Equal = 0x2
    ,
    [Description(">")]
    GreaterThan = 0x3
    ,
    [Description("<")]
    LessThan = 0x4
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsDword
Run Code Online (Sandbox Code Playgroud)

标志,使用比特换档样式的显式值

/// <summary>
/// How to compare filter values; values explicitly set using shorthand of bitwise shifting
/// </summary>
[Flags]
public enum ComparisonsBitshift : int {
    [Description("x")]
    None = 0
    ,
    [Description("!=")]
    NotEqual = 1 << 0
    ,
    [Description("=")]
    Equal = 1 << 1
    ,
    [Description(">")]
    GreaterThan = 1 << 2
    ,
    [Description("<")]
    LessThan = 1 << 3
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
    /// </summary>
    [Description("<=")]
    LessThanOrEqual = (Equal | LessThan)
    ,
    /// <summary>
    /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
    /// </summary>
    [Description(">=")]
    GreaterThanOrEqual = (Equal | GreaterThan)
}//--   enum    ComparisonsBitshift
Run Code Online (Sandbox Code Playgroud)

枚举输出:

    Plain enum ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThan      ,        Descr = >,     Value = 3
    Enum = GreaterThan      ,        Descr = >,     Value = 3   // bad: should be GTE
    Enum = LessThan         ,        Descr = <,     Value = 4
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 6

    Plain enum, underlying int ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThan      ,        Descr = >,     Value = 3
    Enum = GreaterThan      ,        Descr = >,     Value = 3   // bad: should be GTE
    Enum = LessThan         ,        Descr = <,     Value = 4
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 6

    Flag enum, implicit values ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3   // bad: should be GT
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3
    Enum = LessThan         ,        Descr = <,     Value = 4
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 6

    Flag enum, explicit values ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThan      ,        Descr = >,     Value = 4
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 6
    Enum = LessThan         ,        Descr = <,     Value = 8
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 10

    Flag enum, explicit values with DWORD ----                  // all of these are weirdly unexpected
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3
    Enum = LessThan         ,        Descr = <,     Value = 4
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 6

    Flag enum, explicit values with DWORD, not underlying int ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 3
    Enum = LessThan         ,        Descr = <,     Value = 4
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 6

    Flag enum, explicit values with bitshifting ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThan      ,        Descr = >,     Value = 4
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 6
    Enum = LessThan         ,        Descr = <,     Value = 8
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 10
Run Code Online (Sandbox Code Playgroud)

参考文献:

  1. [Flags]枚举属性在C#中意味着什么?
  2. MSDN枚举类型
  3. MSDN FlagsAttribute
  4. 按位枚举转换值不是预期的

为了完整起见,我正在用@ kirk-woll的答案正确用法修改我原来的问题

修正了DWORD语法

    /// <summary>
    /// How to compare filter values; values explicitly defined with *correct* DWORD style
    /// </summary>
    [Flags]
    public enum ComparisonsDwordCorrectlyDefined {
        [Description("x")]
        None = 0x0
        ,
        [Description("!=")]
        NotEqual = 0x1
        ,
        [Description("=")]
        Equal = 0x2
        ,
        [Description(">")]
        GreaterThan = 0x4
        ,
        [Description("<")]
        LessThan = 0x8
        ,
        /// <summary>
        /// Combination of <see cref="Equal"/> and <see cref="LessThan"/>
        /// </summary>
        [Description("<=")]
        LessThanOrEqual = (Equal | LessThan)
        ,
        /// <summary>
        /// Combination of <see cref="Equal"/> and <see cref="GreaterThan"/>
        /// </summary>
        [Description(">=")]
        GreaterThanOrEqual = (Equal | GreaterThan)
    }//--   enum    ComparisonsDwordCorrectlyDefined
Run Code Online (Sandbox Code Playgroud)

枚举输出

    Flag enum, explicit values with correct DWORD ----
    Enum = None             ,        Descr = x,     Value = 0
    Enum = NotEqual         ,        Descr = !=,    Value = 1
    Enum = Equal            ,        Descr = =,     Value = 2
    Enum = GreaterThan      ,        Descr = >,     Value = 4
    Enum = GreaterThanOrEqual,       Descr = >=,    Value = 6
    Enum = LessThan         ,        Descr = <,     Value = 8
    Enum = LessThanOrEqual  ,        Descr = <=,    Value = 10
Run Code Online (Sandbox Code Playgroud)

Kir*_*oll 5

您的DWORD十六进制样式是错误的.你增加一个而不是加倍:

NotEqual = 0x1
Equal = 0x2
GreaterThan = 0x3
LessThan = 0x4
Run Code Online (Sandbox Code Playgroud)

应该:

NotEqual = 0x1
Equal = 0x2
GreaterThan = 0x4
LessThan = 0x8
Run Code Online (Sandbox Code Playgroud)

当然,在你开始上面之前,使用十六进制样式显然没有用8:

LessThan = 0x8
GreaterThanOrEqual = 0x10
LessThanOrEqual = 0x20
Run Code Online (Sandbox Code Playgroud)

在这里它有点方便,因为加倍的进展导致简化的模式,而不是在脑中精神上加倍.

  • 哦,为了f***清酒......呃 (2认同)