有没有办法在枚举中添加“所有值”选项而不必在每次将新值添加到枚举时更改其值?
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = ?
}
更新
结束从long继承并使用long.MaxValue
for All选项。
答案 0 :(得分:34)
由于您应该在标志枚举中定义空值,例如None = 0
,定义All
值的最简单方法是简单地反转None
中的所有位。
[Flags]
enum MyEnum
{
None = 0,
A = 1
B = 2,
C = 4,
...
All = ~None
}
请注意,~0
而不是~None
对于无符号的支持类型不起作用,因为它是-1,这对于无符号
编辑:答案被修改为使用反转的None而不是显式常量,例如0x7FFFFFFF或~0,因为这也适用于无符号
答案 1 :(得分:12)
应该是这样的:
[Flags]
public enum SomeEnum
{
SomeValue = 1,
SomeValue2 = 1 << 1,
SomeValue3 = 1 << 2,
SomeValue4 = 1 << 3,
All = SomeValue | SomeValue2 | SomeValue3 | SomeValue4
}
答案 2 :(得分:4)
枚举可以由许多不同长度的整数类型(short,int,long)组成。这使得#FFFFFFFF
解决方案不合适(正如@MarcGravell评论中指出的那样)。
枚举可以由无符号类型组成(uint用于isntance)。这使得-1
解决方案不合适。
我最好的选择是,免维护:
All = ~0
答案 3 :(得分:3)
想法是使用枚举的行为来计算最后一个值。
在所有“真实”枚举值之后添加 Last 字段。
将所有字段等于(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,
}
我在How to use Enum with aditional options (All, None)
回答了这个问题您可以在Enum Trick查看我的博客,了解更多信息和想法。
答案 4 :(得分:2)
不,没有内置任何内容可以使这样的All
选项在枚举更改时自动更新。
您可能希望有一个特殊值(监视器值),这意味着All
(比如-1),即使它不是所有选项的按位总和。
另一种方法是使用一个已打开所有位的值:
All = 0xFFFFFFFF
答案 5 :(得分:0)
你可以使用一个小技巧
(SomeEnum)( (1 << ( Enum.GetValues( typeof(SomeEnum) ).Length ) ) -1 )
如果添加了值为0(None = 0,
)的“无”枚举名称,则需要在长度后加上“-1”。
答案 6 :(得分:0)
如果您使用单独类型的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#不支持enum泛型,否则你可以这样做:
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;
}
哦,好吧:(
答案 7 :(得分:0)
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;
}