背景:按位枚举对于“更具可读性”的比较和检查很有用:即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
没有标志,基础类型 = 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
标志,隐含值
/// <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
标志,显式值
/// <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
标志,使用 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
标志,使用 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
标志,使用位移样式的显式值
/// <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
枚举输出:
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
参考:
为了完整起见,我正在用@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
枚举输出
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