C# 不需要按位枚举强制转换返回值

C# 不需要按位枚举强制转换返回值,c#,enums,bit-manipulation,C#,Enums,Bit Manipulation,我有以下枚举: [Flags] public enum PermissionLevel { User = 1, Administrator = 2, ITStaff = 3, Manager = 4, SuperAdministrator = 6, } 当我这样做时: PermissionLevel permission = (PermissionLevel) dr.GetInt32(i); 我获

我有以下枚举:

[Flags]
    public enum PermissionLevel {
        User = 1,
        Administrator = 2,
        ITStaff = 3,
        Manager = 4,
        SuperAdministrator = 6,
    }
当我这样做时:

PermissionLevel permission = (PermissionLevel) dr.GetInt32(i);
我获得了分配给权限对象的随机权限值。例如,如果我是6岁,我的权限对象返回Administrator | Manager,我应该得到SuperAdministrator。当我将实例转换回整数时,它返回6


我遗漏了什么吗?

您需要确保每个值的组合都是唯一的:

[Flags]
public enum PermissionLevel {
    User = 1,
    Administrator = 2,
    ITStaff = 4,
    Manager = 8,
    SuperAdministrator = 16
}

正如您的枚举当前所示,6可以表示超级管理员或管理员管理者。4可以是管理者或用户| ITStaff等等。

您需要确保每个值的组合都是唯一的:

[Flags]
public enum PermissionLevel {
    User = 1,
    Administrator = 2,
    ITStaff = 4,
    Manager = 8,
    SuperAdministrator = 16
}

正如您的枚举当前所示,6可以表示超级管理员或管理员管理者。4可以是管理者或用户| ITStaff等等。

它没有随机性。如果权限为6,则二进制值为110。有两个值为1的活动标志位、值为4的管理器位和2的管理员位。您设置的SuperAdministrator值6实际上是Manager和Administrator的组合


有时候,这是你想要的行为,但似乎不是你想要的。然后,您应该更改枚举,使每个值都代表一个唯一的位,正如其他答案所示。

它不是随机的。如果权限为6,则二进制值为110。有两个值为1的活动标志位、值为4的管理器位和2的管理员位。您设置的SuperAdministrator值6实际上是Manager和Administrator的组合


有时候,这是你想要的行为,但似乎不是你想要的。然后,您应该更改枚举,使每个值都代表一个唯一的位,正如其他答案所示。

当使用Flags属性进行修饰时,您可以执行您正在执行的操作,这非常好。。CLR告诉您分配给枚举实例的值为,并且管理员或管理员。。。这就是垂直管道,一个按位Or运算符。 从msdn页面

考虑创建一个枚举 常用标志的常数 组合。例如,如果你有 用于文件I/O的枚举 包含 枚举常数Read=1和 写= 2,考虑创建 枚举常量ReadWrite=Read 或者写,它结合了读和写 写入标志。此外,按位 或用于组合标志的操作 可能被认为是先进的 在某些情况下 对于简单的 任务

您可以很容易地声明枚举,如下所示:

   [Flags]public enum PermissionLevel 
    {        
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }
哦,顺便说一句,总是包含一个无值项被认为是好的做法

    [Flags]public enum PermissionLevel 
    { 
       None = 0,       
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }
这种技术非常有用,因为它允许客户端代码使用简洁地表达实际业务意图的语法,根据单个值的子集测试候选值。。。假设价值观是核心个人价值观之一

 if ((candValue & PermissionLevel.SuperAdministrator) == candVal) 
     // tests to see if candValue is Administrator Or Manager 

这将需要2次比较如果您没有权限访问表示SuperAdministrator bitmask=00000110的枚举值(当使用Flags属性修饰时),则可以执行您正在执行的操作,这非常好。。CLR告诉您分配给枚举实例的值为,并且管理员或管理员。。。这就是垂直管道,一个按位Or运算符。 从msdn页面

考虑创建一个枚举 常用标志的常数 组合。例如,如果你有 用于文件I/O的枚举 包含 枚举常数Read=1和 写= 2,考虑创建 枚举常量ReadWrite=Read 或者写,它结合了读和写 写入标志。此外,按位 或用于组合标志的操作 可能被认为是先进的 在某些情况下 对于简单的 任务

您可以很容易地声明枚举,如下所示:

   [Flags]public enum PermissionLevel 
    {        
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }
哦,顺便说一句,总是包含一个无值项被认为是好的做法

    [Flags]public enum PermissionLevel 
    { 
       None = 0,       
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }
这种技术非常有用,因为它允许客户端代码使用简洁地表达实际业务意图的语法,根据单个值的子集测试候选值。。。假设价值观是核心个人价值观之一

 if ((candValue & PermissionLevel.SuperAdministrator) == candVal) 
     // tests to see if candValue is Administrator Or Manager 

如果您无法访问表示SuperAdministrator bitmask=00000110的枚举值,则需要进行两次比较。文档中是否指定了此项?是的,在Flags属性的文档中:有一种简单的方法可以避免此问题:不要使用1,2,4,8。使用1@Charles当前位置可能是合理的组合,但肯定不是问题中的他。一般来说,如果你在做一个组合,你应该使用预定义的名称,而不是一个数字,以使它显然是一个组合。杰森的建议很有说服力
查尔斯:这是你的解释。我只是简单地回答了这个问题,问题就在于这些值不是唯一的。我自己经常在枚举中使用组合值,但这不适用于我在浏览问题时首先想到的这种情况。文档中是否指定了这一点?是的,在Flags属性的文档中:有一种简单的方法可以避免此问题:不要使用1,2,4,8。使用1@Charles当前位置可能是合理的组合,但肯定不是问题中的他。一般来说,如果你在做一个组合,你应该使用预定义的名称,而不是一个数字,以使它显然是一个组合。杰森的建议很好,也很有效。@Charles:这是你的解释。我只是简单地回答了这个问题,问题就在于这些值不是唯一的。我自己经常在枚举中使用组合值,但这不适用于我在浏览问题时首先想到的这种情况。谢谢,你的解释对理解这种枚举的行为非常有用谢谢,你的解释对理解这种枚举的行为非常有用