13

I've got an Enum marked with the [Flags] attribute as follows:

[Flags]
public enum Tag : int
{
    None = 0,
    PrimaryNav = 1,
    HideChildPages = 2,
    HomePage = 4,
    FooterLink = 8
}

On sitemapnodes in my sitemap I store the int value for the tags combination as an attribute.

What I need to do is check if a node has any one of one or more tags, e.g. Tag.PrimaryNav | Tag.HomePage.

I'm struggling with the necessary boolean logic to determine if an Enum value has one or more of the values it's being compared with.

Apologies if this isn't clear. I can provide more information if necessary.

Paul Suart
  • 6,505
  • 7
  • 44
  • 65
  • See also [this answer](https://stackoverflow.com/a/69483892/543814). It handles only checking for "any one of **all defined flags**", but you may be able to adapt it. – Timo Oct 07 '21 at 15:36

8 Answers8

28

You can do that by combining values with | and checking via &.

To check if the value contains either of the tags:

if ((myValue & (Tag.PrimaryNav | Tag.HomePage)) != 0) { ... }

The | combines the enums you're testing (bitwise) and the & tests via bitwise masking -- if the result isn't zero, it has at least one of them set.

If you want to test whether it has both of them set, you can do that as well:

Tag desiredValue = Tag.PrimaryNav | Tag.HomePage;
if ((myValue & desiredValue) == desiredValue) { ... }

Here we're masking off anything we don't care about, and testing that the resulting value equals what we do care about (we can't use != 0 like before because that would match either value and here we're interested in both).

Some links:

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
9

You can use the HasFlag Method to avoid the need for the boolean logic,

Tag Val = (Tag)9;

if (Val.HasFlag(Tag.PrimaryNav))
{
    Console.WriteLine("Primary Nav");
}

if(Val.HasFlag(Tag.HomePage))
{
    Console.WriteLine("Home Page");
}
Sam
  • 7,252
  • 16
  • 46
  • 65
rerun
  • 25,014
  • 6
  • 48
  • 78
2

For bitwise (Flags) enums, an "any of" test is != 0, so:

const Tag flagsToLookFor = Tag.PrimaryNav | Tag.HomePage;
if ((node.Tag & flagsToLookFor) != 0) {
    // has some cross-over with PrimaryNav or HomePage (and possibly others too) 
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
1
var someEnumValue = Tag.PrimaryNav | Tag.HomePage;

To test if the enum contains a given value:

if ((someEnumValue & Tag.PrimaryNav) == Tag.PrimaryNav)
{

}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1
var tag = Tag.HideChildPages | Tag.PrimaryNav;

If ((tag & Tag.PrimaryNav) == Tag.PrimaryNav) {
    // Tag.PrimaryNav set.
}
AxelEckenberger
  • 16,628
  • 3
  • 48
  • 70
1

You could use Jon Skeet's Unconstrained Melody library:

var someEnumValue = Tag.PrimaryNav | Tag.HideChildPages;
someEnumValue.HasAny(Tag.PrimaryNav | Tag.HomePage); // Returns true
Ben Lings
  • 28,823
  • 13
  • 72
  • 81
0

You can use this extension method on enum, for any type of enums:

public static bool IsSingle(this Enum value)
    {
        var items = Enum.GetValues(value.GetType());
        var counter = 0;
        foreach (var item in items)
        {
            if (value.HasFlag((Enum)item))
            {
                counter++;
            }
            if (counter > 1)
            {
                return false;
            }
        }
        return true;
    }
masehhat
  • 650
  • 6
  • 10
0

That's a classic Extension method:

    public static bool HasFlag(this Enum val, Enum t)
    {
            return (Convert.ToUInt64(val) & Convert.ToUInt64(t)) != 0;
    }
ephraim
  • 379
  • 1
  • 3
  • 15
  • Obviously locate it in a public static class, located in a namespace you've added to the "using" in your class – ephraim Oct 13 '20 at 13:33