人们为什么总是使用枚举值0, 1, 2, 4, 8
,而不喜欢0, 1, 2, 3, 4
?
这与位操作等有关吗?
我将不胜感激关于如何正确使用它的一个小样本片段:)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
人们为什么总是使用枚举值0, 1, 2, 4, 8
,而不喜欢0, 1, 2, 3, 4
?
这与位操作等有关吗?
我将不胜感激关于如何正确使用它的一个小样本片段:)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
Answers:
因为它们是二的幂,所以我可以这样做:
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
位未设置,因此该值不传达权限删除)。
它允许将多个标志存储在单个位字段中。
myEnum.IsSet
。我认为这是一个完全没有用的抽象,只能减少键入,但是……
Flags
属性仅能为您提供“漂亮打印”的iirc。您可以将枚举值用作标志,而不管该属性是否存在。
0
不是false
; false
是false
。但是您可以写if((permissions & Permissions.Write) > 0)
。
(permissions & Permissions.Write) == Permissions.Write
现在,您可以使用enum.HasFlag()
如果从其他答案中仍然不清楚,请这样考虑:
[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亿个项目好得多。
enum
拥有40亿成员的的心理形象+1 。可悲的是,可能有人在尝试过。
2 ** -infinity
的幂)。
因为这些值表示二进制中的唯一位位置,所以:
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
是11
二进制,即它不映射到单个设置位,所以您失去了将任意位置的1位映射到有意义的值的能力。
2|3 == 1|3 == 1|2 == 3
。所以,如果你的二进制值00000011
,和你们的旗帜包括值1
,2
和3
,那么你就不会知道,如果这个值表示1 and 3
,2 and 3
,1 and 2
或only 3
。这使它的用处大大减少。
这些用于表示允许枚举值组合的位标志。我认为如果用十六进制表示法写值会更清楚
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
4194304
2 会得到什么?怎么0x400000
样 0x800000
与相比8388608
,将其识别为正确答案要容易得多,并且键入十六进制值也不太容易出错。
0x10000
的幂?是的,它以1、2、4或8开头,之后为全0。您无需在思维上将0x10转换为16(尽管这样做最终可能会成为第二本性),只需将其视为“ 2的幂”即可。
这确实是更多评论,但是由于它不支持格式设置,因此我只想包括一种我用来设置标志枚举的方法:
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
在您希望按字母顺序维护标志的情况下,我发现这种方法在开发过程中特别有用。如果确定需要添加一个新的标志值,则可以按字母顺序插入它,唯一需要更改的值就是它前面的值。
但是请注意,一旦将解决方案发布到任何生产系统(尤其是在枚举没有紧密耦合的情况下(例如通过Web服务)公开),则强烈建议不要更改枚举中的任何现有值。
好答案,这样一地块的......我只想说..如果你不喜欢,或不容易掌握什么<<
语法所要表达的。我个人更喜欢另一种(我敢说,简单枚举声明样式) …
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
(至少对我自己而言)容易理解。排列它们……描述您想要的结果,获得您想要的结果。.无需“计算”。