1

According to this answer we can have generics constrained to System.Enum since C# 7.3.

However, while one can check any flag of an unkown Enum with

HasFlag(Enum flag)

it is not possible so set a flag of an unkown Enum, since there is no SetFlag() and the |-operator is not defined for System.Enum.

Basicly what I want to do is the following:

public static T Combine<T>(this IEnumerable<T> values) where T : System.Enum
    {
        var value = default(T);

        foreach (var v in values)
        {
            value |= v;
        }

        return value;
    }

The C# compiler tells me

The |=-operator cannot be applied to operands of type 'T' and 'T'.

Is it possible to create such an extension method anyways?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150

1 Answers1

2

Thanks to Daniel A. White's comment I could solve it now like this:

    public static T CombineIntEnums<T>(this IEnumerable<T> values) where T : Enum
    {
        int? result = null;

        foreach (var enumVal in values)
        {
            // convert enum to int
            var intVal = Convert.ToInt32(enumVal);

            if (result.HasValue == false)
                result = intVal;

            result |= intVal;
        }

        // convert int to enum
        var val = (T)Enum.ToObject(typeof(T), result ?? 0);

        return val;
    }
  • 1
    @alexei You can't use `(int)enumVal`: 'The type "T" cannot be converted to "int"'' – SmallestUncomputableNumber Jan 08 '19 at 21:28
  • 3
    This will break for any enums not backed by an `int`. The compiler was *correct* in preventing you from casting it. Just turning it into a runtime error is just obscuring the bug. – Servy Jan 08 '19 at 21:40
  • @Servy if you write this as the answer I'll gladly accept it but for the moment this extension method comes in handy for me – SmallestUncomputableNumber Jan 08 '19 at 21:52
  • Seems to work with everything except Long/ULong (OverflowException) changing it to `ToInt64()` should be fine (unless you're using a lot, then you might have to use BigInteger). – Erik Philips Jan 08 '19 at 23:50