有没有一种方法可以在枚举中添加一个“所有值”选项,而不必每次添加新值时都更改它的值?
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = ?
}
更新:
最终采用从long类继承并使用long.MaxValue
来表示全选选项。
有没有一种方法可以在枚举中添加一个“所有值”选项,而不必每次添加新值时都更改它的值?
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = ?
}
更新:
最终采用从long类继承并使用long.MaxValue
来表示全选选项。
在Flags
枚举类型中,应该定义空值,例如None = 0
。因此,定义All
值最简单的方法是通过反转None
中的所有位。
[Flags]
enum MyEnum
{
None = 0,
A = 1,
B = 2,
C = 4,
...
All = ~None
}
请注意,对于无符号的基础类型而言,使用~None
而不是~0
将无法工作,因为~None
等于-1,这是无符号类型的非法值。
编辑:答案已修改为使用倒置的None而不是显式常数(例如0x7FFFFFFF或~0),因为这对于无符号仍然有效。〜0
,其功能相同。我只是看到所有那些F挨在一起就感到困惑。 - Wells应该像这样:
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = SomeValue | SomeValue2 | SomeValue3 | SomeValue4
}
枚举可以由许多不同长度的整数类型(short、int、long)组成。这使得#FFFFFFFF
的解决方案不合适(正如@MarcGravell评论中指出的那样)。
枚举可以由无符号类型(如uint)组成。这使得-1
的解决方案不合适。
我的最佳选择是,无需维护:
All = ~0
(Last << 1) - 3
的All字段。[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
// Do not add values after this
Last,
All = (Last << 1) - 3,
}
All = ((Last - 1) << 1) - 1
对吧? - Jörgen SigvardssonLAST
= 1001
= 最后一个标志 + 1。LAST << 1
= 10010
= 下一个 标志 + 2。从中减去3,您将得到下一个标志 - 1 (10000 - 1
= 在我们的示例中为1111
),即所有实际值。 - Alicia不,目前没有任何内置功能可以在枚举值改变时自动更新All
选项。
您可能需要一个特殊的值(监视值),表示All
(例如-1),即使它不是所有选项的按位和。
另一种选择是使用一个具有所有位开启的值:
All = 0xFFFFFFFF
你可以使用一个小技巧
(SomeEnum)( (1 << ( Enum.GetValues( typeof(SomeEnum) ).Length ) ) -1 )
None = 0,
),则需要在长度之后放置'-1'。如果您可以接受在单独的类型中使用 static readonly
字段而不是 const
枚举字段,则可以实现此操作:
[Flags]
public enum SomeEnum
{
None = 0,
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
}
public static class SomeEnumUtility {
private static readonly SomeEnum[] _someEnumValues = (SomeEnum[])Enum.GetValues( typeof(SomeEnum) );
public static readonly SomeEnum SomeEnum_All = GetSomeEnumAll();
// Unfortunately C# does not support "enum generics" otherwise this could be a generic method for any Enum type
private static SomeEnum GetSomeEnumAll() {
SomeEnum value = SomeEnum.None; // or `(SomeEnum)0;` if None is undefined.
foreach(SomeEnum option in _someEnumValues) {
value |= option;
}
return value;
}
}
然后你可以得到SomeEnumUtility.SomeEnum_All
。由于它是一个static readonly
,计算只会在线程安全的情况下执行一次。
正如我在代码注释中所写的那样,不幸的是C#不支持枚举泛型,否则你可以这样做:
private static TEnum GetEnumAllFlags<TEnum>() where TEnum : enum {
TEnum[] allValues = Enum.GetValues<TEnum>();
TEnum value = (TEnum)0;
foreach(TEnum option in allValues) {
value |= option;
}
return value;
}
哦,好吧 :(
<EnumBaseType(like int, byte)>.MaxValue
,或者None
和All=~None
选项。 - Hassan Faghihipublic static T EnumSetAll<T>() where T : struct, Enum
{
string str = string.Join(", ", Enum.GetNames(typeof(T)));
if (Enum.TryParse<T>(str, out var e))
return e;
return default;
}
[Flags]
枚举的离散位,因此它应该完全正常。 - Marc Gravell