I need to detect if a flag is set within an enum value, which type is marked with the Flag attribute.
Usually it is made like that:
(value & flag) == flag
But since I need to do this by generic (sometimes at runtime I event have only an "Enum" reference. I can not find an easy way to use the & operator. At the moment I make it like this:
public static bool IsSet<T>(this T value, T flags) where T : Enum
{
Type numberType = Enum.GetUnderlyingType(typeof(T));
if (numberType.Equals(typeof(int)))
{
return BoxUnbox<int>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(sbyte)))
{
return BoxUnbox<sbyte>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(byte)))
{
return BoxUnbox<byte>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(short)))
{
return BoxUnbox<short>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(ushort)))
{
return BoxUnbox<ushort>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(uint)))
{
return BoxUnbox<uint>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(long)))
{
return BoxUnbox<long>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(ulong)))
{
return BoxUnbox<ulong>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(char)))
{
return BoxUnbox<char>(value, flags, (a, b) => (a & b) == b);
}
else
{
throw new ArgumentException("Unknown enum underlying type " + numberType.Name + ".");
}
}
private static bool BoxUnbox<T>(object value, object flags, Func<T, T, bool> op)
{
return op((T)value, (T)flags);
}
But I don't like the never ending if - else blocks, so is there a way to cast these values that I can use the & operator or any other solution to check this?
For me it looks overcomplicated. How about this (keeping in mind that enum is always mapped to an integer value type):
public static bool IsSet<T>(T value, T flags) where T : struct
{
// You can add enum type checking to be perfectly sure that T is enum, this have some cost however
// if (!typeof(T).IsEnum)
// throw new ArgumentException();
long longFlags = Convert.ToInt64(flags);
return (Convert.ToInt64(value) & longFlags) == longFlags;
}