Search code examples
c#enumsgeneric-method

Before C# 7.3 arrives how to get generic method constrained to Enums to compile/work


C# is cool and will allow comparison of Enums and then convert to strings. I already got from SO some code to enumerate the individual items of an Enum (top method in class below). Then, in second method (that I wrote) I managed to convert to string when an enum matches a given value.

The third method, I would like some help with. Given a flag based enum where the given value is in fact many values AND'ed together, I want to atomise the values and convert to a List<string>. If I had C# 7.3 then I think limiting the <T> to an enum might help the compilation. Until then, how can achieve the goal of decomposing a flag enum into atomic values converted to strings.

public static class EnumUtil
{
    // JaredPar https://stackoverflow.com/questions/972307/can-you-loop-through-all-enum-values#answer-972323
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    // S Meaden
    public static string MatchFirst<T>  (T matchThis)
    {
        T[] values = (T[])EnumUtil.GetValues<T>();
        foreach (T val in values)
        {
            if (matchThis.Equals(val))
            {
                return val.ToString();
            }
        }
        return "";
    }

    // S Meaden
    // C# 7.3 https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters#enum-constraints
    public static List<string> MatchFlags<T> (T matchThis) where T : System.Enum
    {
        List<string> flags = new List<string>();

        T[] values = (T[])EnumUtil.GetValues<T>();

        long lMatchThis = (long)matchThis;
        foreach (T val in values)
        {
            long lVal = val;
            //if (lMatchThis & lVal)
            if (matchThis & val)
            {
                flags.Add(val.ToString());
            }
        }
        return flags;
    }
}

Can't get past C# 7.2.

enter image description here


Solution

  • Use where T : struct and throw an ArgumentException if not a System.Enum:

    public static List<string> MatchFlags<T> (T matchThis) where T : struct
    {
        if (!(matchThis is System.Enum)) {
            throw new ArgumentException("Gotta be an enum");
        }
        //etc.
    }
    

    If you have a flags enum and you want to convert it into a List<string>, do something like this:

    matchThis.ToString().Split(',').ToList();