标记 Enum.HasFlag 多个位字段未按预期工作

Flags Enum.HasFlag not Working as Expected for Multiple bit fields

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

true if the bit field or bit fields that are set in flag are also set in the current instance; otherwise, false.

我希望给出一个枚举:

[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 方法?如果可以,怎么做?

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

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

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

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

或者,如果您传入了一组位标志,例如 mask:

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

关于 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)