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

本文关键字:是什么 内部 HasFlag 函数 实现 Enum | 更新日期: 2023-09-27 18:32:03

有人可以帮我理解枚举类的 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是通过代码选择的呢?

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

正如您在下面的链接中看到的那样,HasFlag返回thisInstance的结果,并且标志=标志表达式

埃努姆·哈斯旗帜

请参阅备注部分

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

select * from SecondTable where FlagColumn & 5 = 5

如果我必须实现方法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 类型没有实现 & 运算符,这使得我们在尝试手动比较标志时更加困难。它们必须在枚举的基础类型(实现&运算符)中强制转换。

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