为什么枚举权限通常有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.ReadPermissions.WritePermissions.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对我来说)要容易得多。 排列那些…描述你想要的结果,得到你想要的结果。没有“计算”是必要的。