为什么人们总是使用0, 1, 2, 4, 8
而非0, 1, 2, 3, 4
等枚举值?
这与位操作等有关吗?
我真的很感激有关如何正确使用它的小样本片段:)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
答案 0 :(得分:264)
因为他们是两个人的权力,我可以这样做:
var permissions = Permissions.Read | Permissions.Write;
也许以后......
if( (permissions & Permissions.Write) == Permissions.Write )
{
// we have write access
}
这是一个位字段,其中每个设置位对应于某些权限(或逻辑上对应的枚举值)。如果这些被定义为1, 2, 3, ...
,您将无法以这种方式使用按位运算符并获得有意义的结果。深入研究......
Permissions.Read == 1 == 00000001
Permissions.Write == 2 == 00000010
Permissions.Delete == 4 == 00000100
注意这里的模式?现在,如果我们采用我的原始例子,即
var permissions = Permissions.Read | Permissions.Write;
则...
permissions == 00000011
请参阅? Read
和Write
位都已设置,我可以独立检查(同时注意Delete
位不设置,因此该值不传达删除权限)。
它允许在一个位字段中存储多个标志。
答案 1 :(得分:144)
如果其他答案仍然不清楚,请考虑这样:
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
只是一种较短的写作方式:
public enum Permissions
{
DeleteNoWriteNoReadNo = 0, // None
DeleteNoWriteNoReadYes = 1, // Read
DeleteNoWriteYesReadNo = 2, // Write
DeleteNoWriteYesReadYes = 3, // Read + Write
DeleteYesWriteNoReadNo = 4, // Delete
DeleteYesWriteNoReadYes = 5, // Read + Delete
DeleteYesWriteYesReadNo = 6, // Write + Delete
DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
}
有八种可能性,但您可以将它们表示为仅有四个成员的组合。如果有十六种可能性,那么您可以将它们表示为仅五个成员的组合。如果有40亿种可能性,那么你可以将它们表示为只有33个成员的组合!显然,只有33个成员,每个(除了零)的权力为2,而不是试图在枚举中命名40亿个项目。
答案 2 :(得分:36)
因为这些值表示二进制中的唯一位位置:
1 == binary 00000001
2 == binary 00000010
4 == binary 00000100
等,所以
1 | 2 == binary 00000011
编辑:
3 == binary 00000011
二进制中的<3>在一个地方和两个地方都由值1表示。它实际上与值1 | 2
相同。因此,当您尝试使用二进制位置作为标志来表示某个状态时,3通常不会有意义(除非有逻辑值实际上是两者的组合)
有关进一步说明,您可能希望扩展示例枚举,如下所示:
[Flags]
public Enum Permissions
{
None = 0, // Binary 0000000
Read = 1, // Binary 0000001
Write = 2, // Binary 0000010
Delete = 4, // Binary 0000100
All = 7, // Binary 0000111
}
因此,我有Permissions.All
,我也隐含地Permissions.Read
,Permissions.Write
和Permissions.Delete
答案 3 :(得分:9)
[Flags]
public Enum Permissions
{
None = 0; //0000000
Read = 1; //0000001
Write = 1<<1; //0000010
Delete = 1<<2; //0000100
Blah1 = 1<<3; //0001000
Blah2 = 1<<4; //0010000
}
我认为这样的写作更容易理解和阅读,而且你不需要计算它。
答案 4 :(得分:5)
这些用于表示允许枚举值组合的位标志。如果用十六进制表示法编写值,我认为更清楚
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
答案 5 :(得分:1)
这真的是一个评论,但由于那不支持格式化,我只想包含一个我用来设置标志枚举的方法:
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
在您希望按字母顺序维护标志的情况下,我发现这种方法在开发过程中特别有用。如果您确定需要添加新的标记值,则可以按字母顺序插入,并且您需要更改的唯一值是它现在的值。
但是,请注意,一旦将解决方案发布到任何生产系统(特别是如果枚举是在没有紧密耦合的情况下暴露,例如通过Web服务),那么强烈建议不要更改枚举中的任何现有值
答案 6 :(得分:1)
很多对这个问题的好答案......我只会说..如果你不喜欢,或者不能轻易掌握 <<
语法试图表达的内容......我个人更喜欢另一种选择(我敢说,直截了当的枚举声明风格)...
typedef NS_OPTIONS(NSUInteger, Align) {
AlignLeft = 00000001,
AlignRight = 00000010,
AlignTop = 00000100,
AlignBottom = 00001000,
AlignTopLeft = 00000101,
AlignTopRight = 00000110,
AlignBottomLeft = 00001001,
AlignBottomRight = 00001010
};
NSLog(@"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);
LOG 513 == 513
更容易理解(至少对我自己而言)。排列那些...描述你想要的结果,得到你想要的结果..不需要“计算”。