题
有时我看到一枚举如下:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
我不明白究竟是什么 [Flags]
-属性。
任何人都有一个很好的解释或实例,他们可以帖子?
解决方案
的 [Flags]
属性应用时可枚举的代表收集的可能值,而不是一个单一的价值。这样的集合,是经常使用的按位运营商,例如:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
注意, [Flags]
属性 不不 启用这一通过本身--它所做的是允许一个漂亮的陈述 .ToString()
方法:
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
它也是重要的是要注意 [Flags]
不不 自动使枚举,值力量的两个。如果你忽略的数值,该枚举不会的工作作为一个可能期望在按位的操作,因为默认的价值观开始用0和递增。
不正确的宣言:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
值,如果宣布这种方式,将黄=0、绿色=1,Red=2,Blue=3.这将使其无法作为标志。
这里的一个实例是正确的声明:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
检索的不同价值在你的酒店、一个可以做这样的:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
或之前进行。净4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
盖下
这工作是因为你使用权的两个在你枚举。下面,你列举的数值看起来像这样的二元和零:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
同样,在设置你的财产 AllowedColors 红色,绿色和蓝色使用的二进制位或 |
操作员, AllowedColors 看起来是这样的:
myProperties.AllowedColors: 00001110
所以当你找回你的价值是实际执行按位和 &
在本价值观:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
无=0值
和关于使用 0
在枚举,引用MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
使用没有标志的名称所列举的恒定的,其价值为零。 你不能使用没有列举的恒定在一个按位与操作测试用于一个标志,因为结果都是零。 但是,可以执行的一个合乎逻辑的,不是一位,比较之间的数值而没有列举不断,以确定是否有任何位的数值。
其他提示
你也可以这样做
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
我找到位变更易于输入4,8,16,32等。它没有影响你的代码,因为这一切都完成了在编制时间
合并的答案 https://stackoverflow.com/a/8462/1037948 (《宣言》通过位移)和 https://stackoverflow.com/a/9117/1037948 (使用组合宣言》)可以移位之前的价值,而不是使用数字。不一定是建议,但是指出你可以的。
而不是:
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
Two = 1 << 1, // 2
Three = 1 << 2, // 4
Four = 1 << 3, // 8
// combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
你可以声明
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
// now that value 1 is available, start shifting from there
Two = One << 1, // 2
Three = Two << 1, // 4
Four = Three << 1, // 8
// same combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
确认与LinqPad:
foreach(var e in Enum.GetValues(typeof(Options))) {
string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}
结果:
None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
请看以下例子,这显示了《宣言》和潜在用途:
namespace Flags
{
class Program
{
[Flags]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
我 问最近 关于类似的东西。
如果您使用的标志,你可以添加一个扩展方法,以枚举的做检查所载的标志更容易(见后为详细地)
这可以让你这样做:
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
然后你可以这样做:
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
我找到这种更易于阅读于大多数方法的检查包括的标志。
在扩展到接受的答案,在C#7枚举标志可以写入使用的二进制文字:
[Flags]
public enum MyColors
{
None = 0b0000,
Yellow = 0b0001,
Green = 0b0010,
Red = 0b0100,
Blue = 0b1000
}
我认为这种表示方式清楚地表明如何的标志工作 盖下.
@Nidonocu
添加另一个标志到现有的整套价值观、使用或转让操作。
Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
&& ((Mode & Mode.Read) == Mode.Read)));
添加 Mode.Write
:
Mode = Mode | Mode.Write;
有一些过于详细,我有关 if ((x & y) == y)...
建造,尤其是如果 x
和 y
都是化合物设置标志和你只要知道,如果有的 任何 重叠。
在这种情况下,所有你真的需要知道的是 如果有一个非零值[1]之后你一个位掩码.
[1]见詹姆的评论。如果我们真正的 bitmasking, 我们 只需要检查的结果是积极的。但是,因为
enum
s 可以是负面的、甚至是,奇怪的是,当结合 的[Flags]
属性, 这是防御的代码!= 0
而不是> 0
.
建立@andnil的安装...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BitFlagPlay
{
class Program
{
[Flags]
public enum MyColor
{
Yellow = 0x01,
Green = 0x02,
Red = 0x04,
Blue = 0x08
}
static void Main(string[] args)
{
var myColor = MyColor.Yellow | MyColor.Blue;
var acceptableColors = MyColor.Yellow | MyColor.Red;
Console.WriteLine((myColor & MyColor.Blue) != 0); // True
Console.WriteLine((myColor & MyColor.Red) != 0); // False
Console.WriteLine((myColor & acceptableColors) != 0); // True
// ... though only Yellow is shared.
Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D
Console.Read();
}
}
}
标志允许使用bitmasking内枚举。这可以让你结合举值,而保留其中的规定。
[Flags]
public enum DashboardItemPresentationProperties : long
{
None = 0,
HideCollapse = 1,
HideDelete = 2,
HideEdit = 4,
HideOpenInNewWindow = 8,
HideResetSource = 16,
HideMenu = 32
}
当工作与标志我常常声明的附加没有和所有项目。这些都是有益的,以检查是否所有标志的设置或没有标志的设置。
[Flags]
enum SuitsFlags {
None = 0,
Spades = 1 << 0,
Clubs = 1 << 1,
Diamonds = 1 << 2,
Hearts = 1 << 3,
All = ~(~0 << 4)
}
使用:
Spades | Clubs | Diamonds | Hearts == All // true
Spades & Clubs == None // true