Enum HasFlag函数实现的内部逻辑是什么

时间:2013-09-18 17:49:59

标签: c# asp.net-mvc-3 enums enum-flags

有人可以帮我理解enum类的HasFlag方法的内部逻辑吗? 我先解释一下我的要求。 我已经创建了一个带有flag属性的枚举,然后使用HasFlag()函数从位标志值中获取所选组合。 但在这里,我的要求是不同的。我的数据库中有一个表,列出了不同的枚举值。结构如下。

EnumTypeID    EnumVal      EnumID     Description 
===========  ==========   =========  ================
   1           enum1          0         xxxxxxxxx
   1           enum2          1         xxxxxxxxx
   1           enum3          2         xxxxxxxxx
   2           enum4          0         xxxxxxxxx
   2           enum5          1         xxxxxxxxx

假设我有另一个表,它存储了EnumTypeID 1的最终标志组合。因此,表列可以保存不同的组合,如

0 = Nothing selected
1 = enum1 selected
2 = enum2 selected
3 = enum1 & enum2 selected
4 = enum3 selected
5 = enum1 & enum3 selected
6 = enum2 & enum3 selected
7 = enum1 & enum2 & enum3 selected

=============================================== ==============

现在我如何以编程方式(在C#.net4.5中)实现这一目标。我需要先查询第一个表并获取特定EnumTypeID的枚举列表。现在我需要从第二个表中获取所选标志的值(假设值为5)。然后我怎么说基本上enum1&通过代码选择enum3?

2 个答案:

答案 0 :(得分:4)

正如您在下面的链接中看到的,HasFlag返回 thisInstance和flag = flag 表达式的结果

Enum.HasFlag

见备注栏目

如果我的问题正确,你需要这样的查询:

select * from SecondTable where FlagColumn & 5 = 5

答案 1 :(得分:0)

如果我必须实现方法Enum.HasFlag,我会这样写。

public static bool HasFlag2(this Enum e, Enum flag)
{
    // Check whether the flag was given
    if (flag == null)
    {
        throw new ArgumentNullException("flag");
    }

    // Compare the types of both enumerations
    if (!e.GetType().IsEquivalentTo(flag.GetType()))
    {
        throw new ArgumentException(string.Format(
            "The type of the given flag is not of type {0}", e.GetType()),
            "flag");
    }

    // Get the type code of the enumeration
    var typeCode = e.GetTypeCode();

    // If the underlying type of the flag is signed
    if (typeCode == TypeCode.SByte || typeCode == TypeCode.Int16 || typeCode == TypeCode.Int32 || typeCode == TypeCode.Int64)
    {
        return (Convert.ToInt64(e) & Convert.ToInt64(flag)) != 0;
    }

    // If the underlying type of the flag is unsigned
    if (typeCode == TypeCode.Byte || typeCode == TypeCode.UInt16 || typeCode == TypeCode.UInt32 || typeCode == TypeCode.UInt64)
    {
        return (Convert.ToUInt64(e) & Convert.ToUInt64(flag)) != 0;
    }

    // Unsupported flag type
    throw new Exception(string.Format("The comparison of the type {0} is not implemented.", e.GetType().Name));
}

它与AND运算符执行二进制比较。更多信息here。 如果需要,您可以在Visual Studio中测试其行为,这是一种扩展方法。

希望它有所帮助。

编辑2014-01-10

Enum类型没有实现&运算符,这使我们在尝试手动比较标记时更加努力。它们必须在枚举的基础类型(实现&运算符)中进行转换。

我更新了我的代码,以便处理枚举的所有可能类型。基本上,我们检索枚举的基础类型并根据它们是有符号还是无符号来转换它们。