枚举-所有选项值
本文关键字:选项 -所 枚举 | 更新日期: 2023-09-27 18:17:35
是否有一种方法来添加一个"所有值"选项的枚举,而不必改变其值每次一个新的值被添加到枚举?
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = ?
}
更新:最终继承了long并使用long.MaxValue
for All选项
既然你应该定义一个空值Flags enum such as
None = 0 , the simplest way of defining the
All value is by simply inverting all the bits in
None ' .
[Flags]
enum MyEnum
{
None = 0,
A = 1,
B = 2,
C = 4,
...
All = ~None
}
请注意,~0
而不是~None
将不能用于无符号的备份类型,因为它是-1,这不是无符号的有效值。
编辑:答案被修改为使用反转None而不是显式常量,如0x7FFFFFFF或~0,因为这也适用于无符号
应该是这样的:
[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评论中指出的那样)。
enum可以由unsigned类型组成(例如:int)。这使得-1
解决方案不合适。
我最好的选择是,免维护:
All = ~0
我们的想法是使用枚举的行为来计算最后的值。
在所有'real'枚举值之后添加最后一个字段。
添加所有字段等于(Last << 1) - 3
。
[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,
}
我回答它在:如何使用Enum与其他选项(All, None)
你可以在Enum Trick查看我的博客获取更多信息和想法
不,当枚举改变时,没有任何构建会使这样的All
选项自动更新。
您可能希望有一个特殊的值(监视器值)来表示All
(例如-1),即使它不是所有选项的按位和。
另一种选择是使用一个所有位都打开的值:
All = 0xFFFFFFFF
你可以使用一个小技巧
(SomeEnum)( (1 << ( Enum.GetValues( typeof(SomeEnum) ).Length ) ) -1 )
如果您添加了一个value = 0 (None = 0,
)的'None' Enum名称,那么您需要在Length后面加上一个'-1'。
如果您同意将static readonly
字段放在单独的类型中,而不是作为const
enum字段,则可以这样做:
[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;
}
public 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;
}