【问题标题】:Flags Enum.HasFlag not Working as Expected for Multiple bit fields [duplicate]标志 Enum.HasFlag 未按预期对多个位字段工作 [重复]
【发布时间】:2021-06-30 14:05:58
【问题描述】:

我有一个包含标志枚举值的记录列表。我正在尝试根据提供的标志过滤一个或多个值。 HasFlag方法说明如下:

如果在标志中设置的位域或位域也在当前实例中设置,则为真;否则为假。

我希望给定一个枚举:

[Flags]
public enum MyFlaggedEnum
{
    Unknown = 0,
    First = 1,
    Second = 2,
    Third = 4,
    Fourth = 8,
    Fifth = 16,
    Sixth = 32
}

并且包含这些值的混合记录集,假设每个标志至少有一个记录:

当我过滤一个值时:

var myFilteredList = MyMainList.Where(w => w.flagValue.HasFlag(MyFlaggedEnum.Third));
// myFilteredList returns the correct subset of records

当我过滤多个值时:

var myFilteredListMultiple = MyMainList.Where(w => w.flagValue.HasFlag(MyFlaggedEnum.First | MyFlaggedEnum.Fourth));
// myFilteredList returns an empty set

我是否滥用了 HasFlag 方法?如果有,怎么做?

我正在寻找一种方法来快速过滤结果,以便它们可以根据它们在运行时提供的过滤器在 datagridview 中显示给用户,并且可以随时更改。我可以根据用户请求的标志过滤器循环遍历它们或合并多个集合,但是,我正在寻找一种干净的方式。

编辑:谁关闭这个问题指的是这个:How to check if any flags of a flag combination are set? 不理解这个问题。不,我没有添加 First |我的枚举的第二个值!!

【问题讨论】:

  • 是的,如果你想检查这两个标志之一,你应该使用w => w.flagValue.HasFlag(MyFlaggedEnum.First) || w.flagValue.HasFlag(MyFlaggedEnum.Fourth),如果你只想要两个标志之一,你应该使用&&
  • 如果你将一些值组合在一起并将它们传递给HasFlag,只有在设置了与传递值对应的所有位时才会返回 true。这是一个 AND 而不是 OR。
  • @juharr 我希望避免以这种方式构建查询,因为我不知道用户将请求哪些标志。我选择了 HasFlag,因为它提到了“位域”。
  • 在这种情况下,请使用常规位逻辑,例如 Sinatr 发布的问题
  • @juharr 你为什么把它作为一个副本关闭?这个答案对我一点帮助都没有,因为我的问题涉及使用 lambda。我在提问之前阅读了它,下面马修的回答立即有所帮助。我希望其他有我具体问题的人仍然可以找到这个问题并得到正确的答案。

标签: c# enums


【解决方案1】:

我建议你避开HasFlag,直接使用位操作:

var myFilteredListMultiple = MyMainList.Where(w => (w.FlagValue & (MyFlaggedEnum.First | MyFlaggedEnum.Fourth)) != 0);

或者,如果您有一组传入的位标志,例如 mask

var myFilteredListMultiple = MyMainList.Where(w => (w.FlagValue & mask) != 0);

【讨论】:

  • Matthew,这非常适合我的需求!我会尽快将此标记为解决方案。
【解决方案2】:

HasFlag 应该表示“拥有所有”还是“拥有任何”存在歧义;它被实施为“拥有一切”。但它也是一个低效(装箱)API,老实说:最好不使用它。例如,您可以添加自己的扩展方法:

public static bool HasAny(this MyFlaggedEnum value, MyFlaggedEnum any)
    => (value & any) != 0;
public static bool HasAll(this MyFlaggedEnum value, MyFlaggedEnum all)
    => (value & all) == all;

并使用.HasAny(MyFlaggedEnum.First | MyFlaggedEnum.Fourth)

【讨论】:

  • 谢谢你,马克。我相信我也为这种模棱两可而堕落。
猜你喜欢
  • 1970-01-01
  • 2018-08-15
  • 2019-12-25
  • 1970-01-01
  • 2017-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-06-06
  • 2021-11-28
相关资源
最近更新 更多