3

Can someone please help me to understand the internal logic of HasFlag method for a enum class? Let me first explain my requirement. I have already created an enum with flag attribute, and then used HasFlag() function to get selected combination from a bit flag value. But here my requirement is different. I have a table in my DB, which is having different enumeration values listed. the structure is like below.

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

Let's say I have another table, which is storing the final flag combination for EnumTypeID 1. So that table column is suppose to save different combination like

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

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

Now how can I programmatically(in C# .net4.5) achieve this. I need to first query the first table and get the list of enumeration for a specific EnumTypeID. Now I need to get the value from the second table for the selected flag (let's say the value is 5). Then how I can say that basically enum1 & enum3 is selected through code?

Subhendu Roy
  • 63
  • 3
  • 8
  • 1
    I don't know about anyone else, but I'm very confused by your question. Do you have an actual C# enum anywhere? If so, it would really help if you could post that... – Jon Skeet Sep 18 '13 at 17:53
  • Actually I don't want to create a Enum, but want to use the concept of Enum flag attribute. My enums would be coming from DataBase. based on the values of those enumIds I need to write some code which will dynamically create the 2 to the power values. And then I need to compare that with the Flag values from DB again. – Subhendu Roy Sep 18 '13 at 18:20

2 Answers2

4

as you can see in the below link the HasFlag returns the result of thisInstance And flag = flag expression

Enum.HasFlag

see remarks section

and if I got your question correctly you need a query like this:

select * from SecondTable where FlagColumn & 5 = 5
Karim
  • 150
  • 6
1

If I had to implement the method Enum.HasFlag, I would write it like that.

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));
}

It performs a binary comparison with the AND operator. More info here. If needed, you can test its behavior in Visual Studio, it's an extension method.

Hope it helps.

EDIT 2014-01-10

The Enum type doesn't implement the & operator, making our work harder when trying to compare the flags manually. They must be casted in the underlying type of the enumeration (which implements the & operator).

I updated my code in order to handle all the possible types for an enumeration. Basically, we retrieve the underlying type of the enumeration and cast them depending whether they are signed or unsigned.

Community
  • 1
  • 1
Jämes
  • 6,945
  • 4
  • 40
  • 56
  • An `enum` need not use an `int` as its underlying representation; your method will fail with any that use something else. – supercat Jan 10 '14 at 17:41
  • @supercat: Thanks for your comment, you are right. I updated my post in order to take that into account. – Jämes Jan 10 '14 at 23:18
  • If I define an enum `[Flags]enum MyEnum{A=1, B=2, C=4, D=8}` then `(MyEnum.B|MyEnum.C).HasFlag(MyEnum.C|MyEnum.D)` returns false whereas `(MyEnum.B|MyEnum.C).HasFlag2(MyEnum.C|MyEnum.D)` returns true. This is because HasFlag tests `(e&flag)==flag` rather than `(e&flag)!=0`. Which is a pity, as I wanted the behaviour of your version :) – Joel Rein Apr 23 '15 at 17:30
  • 1
    Enum.HasFlag performs a & b == b, not a & b != 0. So if passed more than one flag, it checks that all flags are contained, not any one of them is contained. – Marco Mp Jan 16 '16 at 22:31