简体   繁体   English

应该“或”与 .Net4 Hasflags 一起使用: enum.HasFlag(AccessRights.Read | AccessRights.Write)

[英]Should "or" work with .Net4 Hasflags: enum.HasFlag(AccessRights.Read | AccessRights.Write)

I am trying out the new HasFlags features, and was wondering if the following should work:我正在尝试新的 HasFlags 功能,并想知道以下是否可行:

enum.HasFlag(AccessRights.Read | AccessRights.Write) enum.HasFlag(AccessRights.Read | AccessRights.Write)

... because it doesn't seem to... ......因为它似乎没有......

 DBAccessRights rights = (DBAccessRights)permission.PermissionFlags;
  if (rights.HasFlag(DBAccessRights.WikiMode))
  {
     // works
  }


  if (rights.HasFlag(DBAccessRights.WikiMode | DBAccessRights.CreateNew))
  {
     // Doesn't work    
  }

  DBAccessRights flags = DBAccessRights.WikiMode | DBAccessRights.CreateNew;
  if (rights.HasFlag(flags))
  {
     // Doesn't work
  }

Given the documentation , I'd expect that to return true if the value has both of those flags. 给定文档 ,如果该值同时具有这两个标志,则我希望它返回true。

If you want it to test whether your value has either of those flags, you'll need 如果你把它想测试你的值是否有任何的标志,你需要

value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write)

If that's not good readable enough for you, you may want to look at my Unconstrained Melody project. 如果您对它的可读性不够好,则可能要看一下我的“ 不受约束的旋律”项目。 It so happens that that already has the functionality you want (as extension methods in Flags.cs ): 碰巧它已经具有您想要的功能(作为Flags.cs扩展方法):

// Same as value.HasFlag(AccessRights.Read | AccessRights.Write)
value.HasAll(AccessRights.Read | AccessRights.Write)

// Same as value.HasFlag(AccessRights.Read) | value.HasFlag(AccessRights.Write)
value.HasAny(AccessRights.Read | AccessRights.Write)

Those would make it clearer, IMO. 国际海事组织,这将使情况更清楚。 They'd also avoid boxing, and be typesafe :) 他们还将避免装箱,并保持类型安全:)

From MSDN : MSDN

The HasFlag method returns the result of the following Boolean expression. HasFlag方法返回以下布尔表达式的结果。

thisInstance And flag = flag thisInstance和flag =标志

For a complex flag such as AccessRights.Read | AccessRights.Write 对于复杂的标志,例如AccessRights.Read | AccessRights.Write AccessRights.Read | AccessRights.Write , this will check that all the "contained" flags are present. AccessRights.Read | AccessRights.Write ,这将检查是否存在所有 “包含”标志。

You probably want to check that any of the flags are present, in which case you can do: 您可能要检查是否存在任何标志,在这种情况下,您可以执行以下操作:

myAccessRights & (AccessRights.Read | AccessRights.Write) != 0 

The | | operator is bitwise or. 运算符是按位或。 It means that if Read is 1 and Write is 2, the value Read | Write 这意味着如果Read为1且Write为2,则值Read | Write Read | Write is 3 (see its binary representation). Read | Write为3(请参见其二进制表示形式)。 So HasFlag returns true only if your enum variable have both Read and Write set. 因此,仅当您的enum变量同时设置 ReadWrite HasFlag返回true。

Alternatively, you could just reverse the order of the expression: 另外,您可以颠倒表达式的顺序:

//returns true - a bit easier on the eye
(AccessRights.Read | AccessRights.Write).HasFlag(myAccessRights)

This will return true if you have either Read | 如果您具有读取” |“返回”,它将返回true。 Write access. 写访问。 That would be functionally equivalent to: 这在功能上将等效于:

//also returns true - as per @Ani's answer
myAccessRights & (AccessRights.Read | AccessRights.Write) != 0

EDIT 编辑

As pointed out in the comments, The first expression will return true if myAccessRights is empty, and false if myAccessRights has more than just Read and Write. 如注释中所指出的,如果myAccessRights为空,则第一个表达式将返回true;如果myAccessRights不仅仅是Read和Write,则第一个表达式将返回false。

In a flagged enum you could simply do:在标记的枚举中,您可以简单地执行以下操作:

(MyEnum01 & MyEnum02) != 0

If there are any common bits, a bit will be set and thus the number is no longer 0. If there are no common bits, the result is 0. For that the flagged enum for 0 should represent "none".如果有任何公共位,则将设置一个位,因此该数字不再为 0。如果没有公共位,则结果为 0。为此,标记为 0 的枚举应表示“无”。

Here is a static method for generic enums and one for a specific one:这是通用枚举的静态方法和特定枚举的静态方法:

public static partial class UtilityMethods
{
    public static bool HasAnyFlags (Enum enumA, Enum enumB)
    {
        return ((int) (object) enumA & (int) (object) enumB) != 0;
    }

    public static bool HasAnyFlags (MyEnum enumA, MyEnum enumB)
    {
        return (enumA & enumB) != 0;
    }
}

You could also create your own extension method:您还可以创建自己的扩展方法:

public static partial class ExtensionMethods
{
    public static bool HasAnyFlag (this Enum e, Enum compared)
    {
        return ((int) (object) e & (int) (object) compared) != 0;
    }
}

For the generic enums I took the conversion from here .对于通用枚举,我从这里进行了转换。 Allegedly it's more performant to do it with boxing rather than Converter.ToInt32() .据称,使用 boxing 而不是Converter.ToInt32()来执行它的性能更高。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM