我花了几个小时试图找出将枚举掩码转换为枚举值数组的通用方法,相反,将Enum值数组转换为其枚举掩码。
编写扩展方法这样做有点痛苦所以我只是想分享我的解决方案,以防它可以帮助某人。我确定它可以改进,但是,这就是它!
答案 0 :(得分:5)
下面的扩展方法从枚举值列表中返回一个掩码。
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());
}
下面的扩展方法返回掩码中的枚举值列表。
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;
}
}
}
请注意:
where T : ...
)中的通用约束不能将T限制为枚举[Flags]
属性(无法弄清楚)用法:
[Flags]
public enum TestEnum : int
{
None = 0,
Plop = 1,
Pouet = 2,
Foo = 4,
Bar = 8
}
掩盖:
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);
要价值观:
TestEnum flags = TestEnum.None | TestEnum.Plop | TestEnum.Foo;
TestEnum[] array = flags.ToValues().ToArray();
TestEnum[] expectedArray = new[] { TestEnum.Plop, TestEnum.Foo };
CollectionAssert.AreEqual(expectedArray, array);
答案 1 :(得分:4)
我需要一个简单的解决方案来转换相反的方向(而不是必须包含扩展名),所以这里有一个Linq解决方案将你的枚举的IEnumerable转换成一个标记的枚举:
MyEnum e = MyEnumList.Aggregate((MyEnum)0, (a,b) => a |= b);