3

有人可以帮我理解枚举类的 HasFlag 方法的内部逻辑吗?让我先解释一下我的要求。我已经创建了一个带有标志属性的枚举,然后使用 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 是通过代码选择的呢?

4

2 回答 2

4

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

Enum.HasFlag

见备注部分

如果我正确地回答了您的问题,您需要这样的查询:

select * from SecondTable where FlagColumn & 5 = 5
于 2013-09-18T17:58:58.140 回答
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。更多信息在这里。如果需要,您可以在 Visual Studio 中测试其行为,这是一种扩展方法。

希望能帮助到你。

编辑 2014-01-10

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

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

于 2013-09-18T18:34:57.373 回答