C# 将枚举值与位标志相结合
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19582477/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Combining Enum Values with Bit-Flags
提问by Vincent Dagpin
I have this scenario where user has its role
我有这样一个场景,其中用户有它的角色
NormalUser
Custodian
Finance
普通用户
托管
财务
both Custodian and Finance is a SuperUser
托管人和财务都是超级用户
How can i check if a role Custodianis a SuperUser
我如何检查角色保管人是否是超级用户
this is my sample code..
这是我的示例代码..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
public enum Role
{
NormalUser = 0,
Custodian = 1,
Finance = 2,
SuperUser = Custodian | Finance,
All = Custodian | Finance | NormalUser
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Normal: " + Convert.ToInt32(Role.NormalUser));
Console.WriteLine("Custodian: " + Convert.ToInt32(Role.Custodian));
Console.WriteLine("Finance: " + Convert.ToInt32(Role.Finance));
Console.WriteLine("SuperUser: " + Convert.ToInt32(Role.SuperUser));
Console.WriteLine("All: " + Convert.ToInt32(Role.All));
Console.WriteLine();
Console.WriteLine("Normal User is in All: {0}", Role.NormalUser == Role.All);
Console.WriteLine("Normal User is not a SuperUser: {0}", Role.NormalUser != Role.SuperUser);
Console.WriteLine("Normal User is not a Custodian: {0}", Role.NormalUser != Role.Custodian);
Console.WriteLine();
Console.WriteLine("Custodian is in All: {0}", Role.Custodian == Role.All);
Console.WriteLine("Custodian is a SuperUser: {0}", Role.Custodian == Role.SuperUser);
Console.WriteLine("Custodian is a NormalUser: {0}", Role.Custodian == Role.NormalUser);
Console.WriteLine();
Console.WriteLine("Finance is in All: {0}", Role.Finance == Role.All);
Console.WriteLine("Finance is a SuperUser: {0}", Role.Finance == Role.SuperUser);
Console.WriteLine("Finance is a NormalUser: {0}", Role.Finance == Role.NormalUser);
Console.ReadLine();
}
}
}
and this is the result if we run it
如果我们运行它,这就是结果
Normal: 0
Custodian: 1
Finance: 2
SuperUser: 3
All: 3
Normal User is in All: False
Normal User is not a SuperUser: True
Normal User is not a Custodian: True
Custodian is in All: False
Custodian is a SuperUser: False
Custodian is a NormalUser: False
Finance is in All: False
Finance is a SuperUser: False
Finance is a NormalUser: False
i am expecting that a
我期待一个
Custodian is in All: True,
Custodian is a SuperUser: True,
Finance is in All: True,
Finance is a SuperUser: True,
Normal User is in All: True
Custodian is in All: True,
Custodian is a SuperUser: True,
Finance is in All: True,
Finance is a SuperUser: True,
Normal User in All: True
采纳答案by David Ewen
Enum.HasFlagis what you want to use
Enum.HasFlag是你想要使用的
Console.WriteLine("Custodian is in All: {0}", Role.All.HasFlag(Role.Custodian));
Just noticed that your enum should be defined like this with the Flags attribute and values spaced out by powers of 2
刚刚注意到你的枚举应该像这样定义 Flags 属性和值以 2 的幂隔开
[Flags]
public enum Role
{
NormalUser = 1,
Custodian = 2,
Finance = 4,
SuperUser = Custodian | Finance,
All = Custodian | Finance | NormalUser
}
The reason powers of 2 are used for flagged enums is that each power of 2 represents a unique bit being set in the binary representation:
2 的幂用于标记枚举的原因是每个 2 的幂代表在二进制表示中设置的唯一位:
NormalUser = 1 = 00000001
Custodian = 2 = 00000010
Finance = 4 = 00000100
Other = 8 = 00001000
Because each item in the enum has a unique bit set this allows them to be combined by setting their respective bits.
因为枚举中的每个项目都有一个唯一的位集,这允许通过设置它们各自的位来组合它们。
SuperUser = 6 = 00000110 = Custodian + Finance
All = 7 = 00000111 = NormalUser + Custodian + Finance
NormOther = 9 = 00001001 = NormalUser + Other
Notice how each 1 in the binary form lines up with the bit set for the flag in the section above.
请注意二进制形式中的每个 1 如何与上一节中为标志设置的位对齐。
回答by Turbofant
You can add the Flag-attribute to the Enum
您可以将 Flag 属性添加到 Enum
[Flags]
public enum Role
{
NormalUser,
Custodian,
Finance,
SuperUser = Custodian | Finance,
All = Custodian | Finance | NormalUser
}
Then you can check for a role with this expression:
然后您可以使用此表达式检查角色:
Role testRole = Role.Finance
if(testRole & Role.SuperUser == Role.SuperUser){
//testRole is SuperUser
}
回答by A.Johansson
I think this might be a duplicate of How do you pass multiple enum values in C#?
我认为这可能是How do you pass multiple enum values in C#的重复?
Where the & bitmask can do the trick.
& 位掩码可以解决问题的地方。
((Role.NormalUser & Role.All) == Role.NormalUser)
Inspecting this closer you will get the following:
仔细检查一下,您将获得以下信息:
0b0 & 0b11 == 0b0
However if you lets say want to check if the SuperUser is in finance you will get the following:
但是,如果您说要检查 SuperUser 是否在财务部门,您将得到以下信息:
((Role.SuperUser & Role.Finance) == Role.Finance)
This will evaluate to:
这将评估为:
0b11 & 0b10 == 0b10
回答by drzaus
Check out What does the [Flags] Enum Attribute mean in C#?for a more thorough explanation.
查看C# 中的 [Flags] 枚举属性是什么意思?以获得更彻底的解释。
A "safer" way to declare flags is to use bit-shifting to ensure there's no overlap (as mentioned by @DaveOwen's answer) without figuring out the math yourself:
声明标志的“更安全”方法是使用位移来确保没有重叠(如@DaveOwen 的回答所述),而无需自己计算数学:
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
There's also Enum.HasFlag
(possibly newer .NET than OP) for checking, rather than Expected & Testing == Expected
还有Enum.HasFlag
(可能比 OP 更新的 .NET)用于检查,而不是Expected & Testing == Expected