按位枚举转换返回值不是预期的

发布于 2024-08-08 23:09:22 字数 437 浏览 2 评论 0原文

我有以下枚举:

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

当我这样做时:

PermissionLevel permission = (PermissionLevel) dr.GetInt32(i);

我得到分配给权限对象的随机权限值。例如,如果 i 为 6,我的权限对象将返回“管理员 | 经理”,并且我应该获得“超级管理员”。当我将实例转换回整数时,它返回 6。

我错过了什么吗?

I have the following enum:

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

When I do:

PermissionLevel permission = (PermissionLevel) dr.GetInt32(i);

I get random permission values assigned to the permission object. For instance, if i is 6, my permission object returns "Administrator | Manager" and I'm supposed to get "SuperAdministrator". When I cast the instance back to integer it returns 6.

Am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海未深 2024-08-15 23:09:22

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

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

正如您的枚举当前所示,6 可以表示 SuperAdministratorAdministrator |经理。 4 可以是ManagerUser | ITStaff 等等。

You need to make sure that each combination of values is unique:

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

As your enum currently looks, 6 can mean either SuperAdministrator or Administrator | Manager. 4 can be either Manager or User | ITStaff and so on.

放血 2024-08-15 23:09:22

这没有什么随机的。如果权限为6,则二进制值为110。有两个活动标志(值为 1 的位),值为 4(管理员)和 2(管理员)的位。您设置的 SuperAdministrator 值 6 实际上是 ManagerAdministrator 的组合。

有时这就是您想要的行为,但它似乎并不适合您的情况。然后,您应该更改枚举,以便每个值代表一个唯一的位,如其他答案所示。

There's nothing random about it. If permission is 6, the binary value is 110. There are two active flags (bits with a value of 1), the bit with the value of 4 (Manager), and 2 (Administrator). The SuperAdministrator value of 6 that you set is actually a combination of Manager and Administrator.

Sometimes that's the behavior that you want, but it doesn't seem to be your case. You should then change your enum so that each value represents a unique bit, as other answers demonstrate.

噩梦成真你也成魔 2024-08-15 23:09:22

当用 Flags 属性装饰时,您可以做您正在做的事情,而且完全没问题。CLR 告诉您分配给枚举实例的值是 Administrator 或 Manager...这就是垂直管道,a按位或运算符。
从 msdn 页面 msdn 标志属性

“考虑创建一个枚举
常用标志常量
组合。例如,如果您有
用于文件 I/O 的枚举
包含的操作
枚举常量 Read = 1 和
Write = 2,考虑创建
枚举常量 ReadWrite = Read
OR Write,结合了读和
写标志。此外,按位
用于组合标志的 OR 运算
可能被认为是先进的
在某些情况下的概念
不应该被要求简单
任务。”

您可以轻松地声明枚举,如下所示:

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

哦,顺便说一句,始终包含 None 值被认为是很好的做法...

    [Flags]public enum PermissionLevel 
    { 
       None = 0,       
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }

这种技术非常有用,因为它允许客户端代码测试候选值使用简洁地表达实际业务意图的语法针对单个值的子集...假设 candValue 是核心单个值之一...

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

如果您无权访问表示超级管理员位掩码的枚举值,则需要进行 2 次比较= 00000110

when decorated with the Flags attribute, you can do what you are doing and it's perfectly fine.. The CLR is telling you that the value assigned to the enum instance is and Administrator Or a Manager... thats what the vertical pipe is, a bitwise Or operator.
From the msdn page msdn Flags Attribute

"Consider creating an enumerated
constant for commonly used flag
combinations. For example, if you have
an enumeration used for file I/O
operations that contains the
enumerated constants Read = 1 and
Write = 2, consider creating the
enumerated constant ReadWrite = Read
OR Write, which combines the Read and
Write flags. In addition, the bitwise
OR operation used to combine the flags
might be considered an advanced
concept in some circumstances that
should not be required for simple
tasks."

You could have just as easily have declared the enum as follows:

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

and oh, btw, it's considered good practice to always include a None value...

    [Flags]public enum PermissionLevel 
    { 
       None = 0,       
       User = 1,        
       Administrator = 2,        
       ITStaff = User | Administrator,        
       Manager = 4,        
       SuperAdministrator = Administrator | Manager ,    
    }

This technique is extremely useful, as it allows client code to test a candidate value against a subset of the individual values using syntax that concisely expresses the actual business intent... assuming candValue is one of core individual values...

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

which would require 2 comparisons if you did not have access to an enum value that represented the SuperAdministrator bitmask = 00000110

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文