我们都知道,C#中可以使用“|”符号来进行Flags枚举的并操作。(事实上非Flags枚举也可以这样做,因为“|”就是二进制并操作,而任何枚举都可以转换成数字。)。但是通常使用“|”操作都是在已知枚举类型的情况下,比如这样:
FileAttributes.System | FileAttributes.Hidden
如果需要隐式类型并操作,则需要先把枚举值统一转换成数字,然后进行二进制并操作,再转换回枚举类型。这里注意:你可以直接把数字转换成一个已知的枚举类型,但是不可以把数字转换成Enum对象,因为Enum对象的类型是未知的。这里必须需要的一个方法就是Enum.ToObject。它可以把一个数字转换成指定类型的枚举Enum对象。他有两个参数,第一个是枚举的类型(Type对象),第二个是数字(int, uint, long, ulong…)。它的第二个参数还有一个object类型的重载,不过其实就是检查object是否是相应数字类型,然后调用对应类型的ToObject方法。
这样的话,我们可以定义一个Flags枚举的隐式类型并操作方法:
static Enum Combine(Type enumType, params Enum[] enums)
{
//参数验证
if (enumType == null)
throw new ArgumentNullException("enumType");
if (enums == null)
throw new ArgumentNullException("enums");
if (!enumType.IsEnum)
throw new ArgumentException("enumType不是枚举类型");
if (enums.Length == 0)
throw new ArgumentException("enums不包含任何成员");
//把值统一转换成long
var longval = Convert.ToInt64(enums[0]);
for (int i = 1; i < enums.Length; i++)
longval = longval | Convert.ToInt64(enums[i]);
return (Enum)Enum.ToObject(enumType, longval);
}
做一个简单的测试,定义一个Flags枚举:
[Flags]
enum MyEnum
{
a = 1, b = 2, c = 4
}
执行:
var enumValue = Combine(typeof(MyEnum), MyEnum.b, MyEnum.c);
Console.WriteLine(enumValue);
输出:
b, c