为什么枚举权限通常有0,1,2,4的值?
为什么人们总是使用枚举值如0,1,2,4,8而不是0, 1, 2, 3, 4
?
这是否与位操作等有关?
我真的很感激如何正确使用这个小样本片段:)
[Flags] public enum Permissions { None = 0, Read = 1, Write = 2, Delete = 4 }
因为他们是两个权力,我可以这样做:
var permissions = Permissions.Read | Permissions.Write;
也许以后…
if( (permissions & Permissions.Write) == Permissions.Write ) { // we have write access }
它是一个位字段,其中每个set位对应某个权限(或者任何枚举值逻辑对应)。 如果这些被定义为1, 2, 3, ...
那么您将无法以这种方式使用按位运算符并获得有意义的结果。 深入研究…
Permissions.Read == 1 == 00000001 Permissions.Write == 2 == 00000010 Permissions.Delete == 4 == 00000100
注意这里的模式? 现在,如果我们拿我最初的例子,
var permissions = Permissions.Read | Permissions.Write;
然后…
permissions == 00000011
看到? Write
位都被设置,我可以单独检查(还要注意, Delete
位没有被设置,因此这个值不能传送删除权限)。
它允许在一个位的一个字段中存储多个标志。
如果还不清楚其他答案,可以这样想:
[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 }
有八种可能性,但可以将它们表示为只有四个成员的组合。 如果有十六种可能性,那么你可以把它们表示为只有五个成员的组合。 如果有四十亿的可能性,那么你可以把它们表示为只有33个成员的组合! 只有33个成员(每个成员除外)都是2的幂,而不是试图命名枚举中的40亿项。
由于这些值以二进制表示唯一的位地址:
1 == binary 00000001 2 == binary 00000010 4 == binary 00000100
等等,所以
1 | 2 == binary 00000011
编辑:
3 == binary 00000011
在二进制中3表示在一个地方和两个地方的值为1。 它实际上与值1 | 2
相同 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
[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 }
我认为这样写更容易理解和阅读,而且不需要计算。
这些用来表示允许组合枚举值的位标志。 我认为如果你用hex表示法写出这些值会更清楚
[Flags] public Enum Permissions { None = 0x00, Read = 0x01, Write = 0x02, Delete= 0x04, Blah1 = 0x08, Blah2 = 0x10 }
这实际上更多的是一个评论,但由于不支持格式化,我只是想包括一个我用来设置标志枚举的方法:
[Flags] public enum FlagTest { None = 0, Read = 1, Write = Read * 2, Delete = Write * 2, ReadWrite = Read|Write }
我发现这种方法在开发过程中特别有用,在这种情况下,您希望按字母顺序维护标志。 如果你确定你需要添加一个新的标志值,你可以按字母顺序插入它,唯一需要改变的值就是它现在的值。
但是请注意,一旦将解决scheme发布到任何生产系统(特别是如果枚举暴露在没有紧密耦合的情况下(例如通过Web服务),则强烈build议不要更改枚举中的任何现有值。
Lot对这个很好的答案…我只是说..如果你不喜欢,或者不能很容易地理解 <<
语法正在试图expression什么……我个人比较喜欢另外一个(我敢说, 直接的枚举声明样式)…
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);
日志 513 == 513
(至less对我来说)要容易得多。 排列那些…描述你想要的结果,得到你想要的结果。没有“计算”是必要的。