C# Enums - Check Flags against a Mask

11,781

Solution 1

You can turn the condition around, and check if the composite enum has the flag, rather than checking the flag for the composite, like this:

if (MemoryProtection.Readable.HasFlag(myMemoryProtection)) {
    ...
}

Here is an example:

MemoryProtection a = MemoryProtection.ExecuteRead;
if (MemoryProtection.Readable.HasFlag(a)) {
    Console.WriteLine("Readable");
}
if (MemoryProtection.Writable.HasFlag(a)) {
    Console.WriteLine("Writable");
}

This prints Readable.

Solution 2

Try bitwise operators:

[TestMethod]
public void FlagsTest()
{
    MemoryProtection mp = MemoryProtection.ReadOnly | MemoryProtection.ReadWrite | MemoryProtection.ExecuteRead | MemoryProtection.ExecuteReadWrite;
    MemoryProtection value = MemoryProtection.Readable | MemoryProtection.Writable;
    Assert.IsTrue((value & mp) == mp);
}

Solution 3

Yes, hasFlag checks if every bit field (flag) is set.

Rather than treating Readable as a composite of all the protections that include Read in the name, can you turn the composition around? E.g.

[Flags]
private enum MemoryProtection: uint
{
    NoAccess         = 0x000,
    Read             = 0x001,
    Write            = 0x002,
    Execute          = 0x004,
    Copy             = 0x008,
    Guard            = 0x010,
    NoCache          = 0x020,
    ReadOnly         = Read,
    ReadWrite        = (Read | Write),
    WriteCopy        = (Write | Copy),
    // etc.
    NoAccess         = 0x800
}

Then you can write code like:

myMemoryProtection.HasFlag(MemoryProtection.Read)
Share:
11,781
Tommaso Belluzzo
Author by

Tommaso Belluzzo

Updated on June 14, 2022

Comments

  • Tommaso Belluzzo
    Tommaso Belluzzo almost 2 years

    I have the following enum flags:

    [Flags]
    private enum MemoryProtection: uint
    {
        None             = 0x000,
        NoAccess         = 0x001,
        ReadOnly         = 0x002,
        ReadWrite        = 0x004,
        WriteCopy        = 0x008,
        Execute          = 0x010,
        ExecuteRead      = 0x020,
        ExecuteReadWrite = 0x040,
        ExecuteWriteCopy = 0x080,
        Guard            = 0x100,
        NoCache          = 0x200,
        WriteCombine     = 0x400,
        Readable         = (ReadOnly | ReadWrite | ExecuteRead | ExecuteReadWrite),
        Writable         = (ReadWrite | WriteCopy | ExecuteReadWrite | ExecuteWriteCopy)
    }
    

    Now i have an enum instance that I need to check if it's readable. If I use the following code:

    myMemoryProtection.HasFlag(MemoryProtection.Readable)
    

    It always returns false in my case because I think HasFlag check if it has every flag. I need something elegant to avoid doing this:

    myMemoryProtection.HasFlag(MemoryProtection.ReadOnly)         ||
    myMemoryProtection.HasFlag(MemoryProtection.ReadWrite)        ||
    myMemoryProtection.HasFlag(MemoryProtection.ExecuteRead)      ||
    myMemoryProtection.HasFlag(MemoryProtection.ExecuteReadWrite)
    

    How can I do it?

  • Grinn
    Grinn about 9 years
    Readers should note that HasFlag became available with .NET 4.0.
  • GoldBishop
    GoldBishop over 6 years
    This is the preferred method if you have implemented a bit-mask approach.