将Flags转换为IEnumerable <Enum>的扩展方法,反之(C#)

Ped*_*dro 2 c# ienumerable extension-methods enums

我花了几个小时试图找出一种将枚举掩码转换为枚举值数组的通用方法,相反,我将枚举值的数组转换为其枚举掩码.

写一个扩展方法这样做有点痛苦,所以我只是想分享我的解决方案,以防它可以帮助某人.我相信它可以改进,但是,它在这里!

Ped*_*dro 7

下面的扩展方法从枚举值列表中返回一个掩码.

public static T ToMask<T>(this IEnumerable<T> values) where T : struct, IConvertible
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("T must be an enumerated type.");

     int builtValue = 0;
     foreach (T value in Enum.GetValues(typeof(T)))
     {
        if (values.Contains(value))
        {
            builtValue |= Convert.ToInt32(value);
        }
    }
    return (T)Enum.Parse(typeof(T), builtValue.ToString());
}
Run Code Online (Sandbox Code Playgroud)

下面的扩展方法返回掩码中的枚举值列表.

public static IEnumerable<T> ToValues<T>(this T flags) where T : struct, IConvertible
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("T must be an enumerated type.");

    int inputInt = (int)(object)(T)flags;
    foreach (T value in Enum.GetValues(typeof(T)))
    {
        int valueInt = (int)(object)(T)value;
        if (0 != (valueInt & inputInt))
        {
            yield return value;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:

  1. c#(where T : ...)中的通用约束不能将T限制为Enum
  2. 这些方法不检查Enum是否具有该[Flags]属性(无法弄清楚)

用法:

[Flags]
public enum TestEnum : int
{
    None = 0,
    Plop = 1,
    Pouet = 2,
    Foo = 4,
    Bar = 8
}
Run Code Online (Sandbox Code Playgroud)

掩盖:

TestEnum[] enums = new[] { TestEnum.None, TestEnum.Plop, TestEnum.Foo };
TestEnum flags = enums.ToMask();

TestEnum expectedFlags = TestEnum.None | TestEnum.Plop | TestEnum.Foo;
Assert.AreEqual(expectedFlags, flags);
Run Code Online (Sandbox Code Playgroud)

价值观:

TestEnum flags = TestEnum.None | TestEnum.Plop | TestEnum.Foo;
TestEnum[] array = flags.ToValues().ToArray();

TestEnum[] expectedArray = new[] { TestEnum.Plop, TestEnum.Foo };
CollectionAssert.AreEqual(expectedArray, array);
Run Code Online (Sandbox Code Playgroud)


bra*_*is7 6

我需要一个简单的解决方案来转换相反的方向(而不是必须包含扩展名),所以这里有一个 Linq 解决方案,可以将枚举的 IEnumerable 转换为带标记的枚举:

MyEnum e = MyEnumList.Aggregate((MyEnum)0, (a,b) => a |= b);
Run Code Online (Sandbox Code Playgroud)