为什么枚举权限通常有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
}
22455 次浏览

因为它们是两次幂,我可以这样做:

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

看到没?ReadWrite位都设置好了,我可以独立检查它们(还要注意,Delete位是 没有设置的,因此这个值不传递删除权限)。

它允许用户在一个位字段中存储多个标志。

因为这些值代表二进制中唯一的位位置:

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.ReadPermissions.WritePermissions.Delete

它们用于表示允许枚举值组合的位标志。我觉得用十六进制表示更清楚

[Flags]
public Enum Permissions
{
None =  0x00,
Read =  0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}

如果从其他答案来看还是不清楚,可以这样想:

[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
}

有八种可能性,但是你可以将它们表示为只有四个成员的组合。如果有16种可能性,那么你可以将它们表示为只有5个成员的组合。如果有40亿种可能性,那么你可以将它们表示为只有33个成员的组合!显然,只有33个成员(每个成员(除了零个)是2的幂)要比试图在枚举中命名40亿个项要好得多。

这实际上更像是一个注释,但是因为它不支持格式化,所以我只想包含一个用于设置标志枚举的方法:

[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}

我发现这种方法在开发过程中特别有用,尤其是在你喜欢把旗帜保持在字母顺序的情况下。如果您确定需要添加新的标志值,只需按字母顺序插入该值,需要更改的唯一值就是它现在位于前面的值。

然而,请注意,一旦解决方案被发布到任何生产系统(特别是当枚举没有紧耦合(比如通过 Web 服务)而公开时) ,那么最好不要更改枚举中的任何现有值。

[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
}

我认为使用 二进制移位运算符写作更容易理解和阅读,而且你不需要计算它。

这个问题有很多好答案,我只能说。.如果你不喜欢,或者 不容易掌握什么 <<语法试图表达。.我个人更喜欢另一种方式(我敢说,直截了当枚举声明风格) ..。

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);

LOG513 = = 513

如此容易理解(至少对我来说)。列出那些... 描述你想要的结果,得到你想要的结果。.没有“计算”的必要。