Check if flag contains any value of other flag

823 Views Asked by At

I would like compare two flags and see if they have any common value.
I'ld like having an extension method as weel in order to "speed up" coding (I'm going to use it often and on various Enum types). How can I?
This code tell me:

operator '&' cannot be applied to operands of type enum and enum

public enum Tag
{
    Value1 = 1,
    Value2 = 2,
    Value3 = 4,
    Value4 = 8,
    Value5 = 16
}

public static class FlagExt
{
    public static bool HasAny(this Enum me, Enum other)
    {
        return (me & other) != 0;
    }
}

public class Program
{
    public static void Main()
    {
        Tag flag1 = Tag.Value1 | Tag.Value2 | Tag.Value3;
        Tag flag2 = Tag.Value2 | Tag.Value3 | Tag.Value4;
        
        Console.WriteLine(flag1.HasAny(flag2)); // it should returns true. flag1.HasFlag(flag2) returns false.
    }
}

I tried this as well:

    return (((int)me) & ((int)other)) != 0;

but it raises the error:

Cannot convert type 'System.Enum' to 'int'

3

There are 3 best solutions below

0
On BEST ANSWER

As per this answer (How to convert from System.Enum to base integer?)

You will need to wrap this code with an exception handler or otherwise ensure that both enums hold an integer.

public static class FlagExt
{
    public static bool HasAny(this Enum me, Enum other)
    {
        return (Convert.ToInt32(me) & Convert.ToInt32(other)) != 0;
    }
}
0
On

I tried this as well:

return (((int)me) & ((int)other)) != 0;

but it raises the error:

Cannot convert type 'System.Enum' to 'int'

Enums always implement IConvertible and IConvertible has 'ToInt32'. So you could write it like this:

public static class FlagExt
{
    public static bool HasAny<TEnum>(this TEnum me, TEnum other) 
            where TEnum : Enum, IConvertible
    {
        return (me.ToInt32(null) & other.ToInt32(null)) != 0;
    }
}

    
0
On

If you want a very generic HasAny extension for enums you could do the following. I've tested that this works with all the different underlying types that an enum can be. Also, if you are checking for flags you should probably have the [Flags] attribute decorating your enum, so this checks that the enums being checked have that attribute.

public static class FlagExtensions
{
    public static bool HasAny(this Enum enumLeft, Enum enumRight)
    {
        if (enumLeft.GetType() != enumRight.GetType())
            throw new ArgumentException("enum types should be the same");
        
        if (!enumLeft.GetType().IsDefined(typeof(FlagsAttribute), inherit: false))
            throw new ArgumentException("enum type should have the flags attribute");
        
        dynamic enumLeftValue = Convert.ChangeType(enumLeft, enumLeft.GetTypeCode());
        dynamic enumRightValue = Convert.ChangeType(enumRight, enumRight.GetTypeCode());
        return (enumLeftValue & enumRightValue) != 0;
    }
}