运营商’|’ 不能应用于’System.Enum’和’System.Enum’类型的操作数

我可以|&等,一个enum ,但不是一个Enum 。 为什么是这样? 有没有办法解决? 我正在尝试为WPF编写一个Enum标志转换器。

 public class EnumFlagConverter : IValueConverter { public Enum CurrentValue; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var theEnum = value as Enum; CurrentValue = theEnum; return theEnum.HasFlag(parameter as Enum); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { Enum CurrentValue; var theEnum = parameter as Enum; if (CurrentValue.HasFlag(theEnum)) //this line is allowed return CurrentValue &= ~theEnum; //~theEnum not allowed, neither is the &= else return CurrentValue |= theEnum; // |= cannot be applied to Enum and Enum } } 

为什么是这样?

在编译器知道枚举的基础类型的情况下,编译器可以执行按位操作而不会出现任何问题。 在编译器不知道底层类型的情况下,它无法知道您是想要一个8位,一个16位,一个32位,甚至是一个64位操作,而只是完全放弃。 另请注意,编译器无法知道您的两个枚举值都不为null ,并且编译器无法知道两个枚举值具有相同的类型甚至宽度。

有没有办法解决?

您可以知道,您永远不会处理大于64位的枚举,并且即使对于8位枚举类型,64位操作也会产生正确的结果。 因此,您可以通过显式将操作编写为64位操作来帮助编译器。

 static Enum Or(Enum a, Enum b) { // consider adding argument validation here if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) | Convert.ToInt64(b)); else return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) | Convert.ToUInt64(b)); } 

同样的And

使用接受的答案,我精心设计了这个转换器,将多个复选框绑定到[Flags]Enum注意:此转换器使用类成员,因此不要为多组绑定重用相同的转换器实例。

XAML:

         

C#:

 public class EnumFlagConverter : IValueConverter { public Enum CurrentValue { get; set; } public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var theEnum = value as Enum; CurrentValue = theEnum; return theEnum.HasFlag(parameter as Enum); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { var theEnum = parameter as Enum; if (CurrentValue.HasFlag(theEnum)) CurrentValue = CurrentValue.And(theEnum.Not()); else CurrentValue = CurrentValue.Or(theEnum); return CurrentValue; } } public static class Extensions { public static Enum Or(this Enum a, Enum b) { // consider adding argument validation here if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) | Convert.ToInt64(b)); else return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) | Convert.ToUInt64(b)); } public static Enum And(this Enum a, Enum b) { // consider adding argument validation here if (Enum.GetUnderlyingType(a.GetType()) != typeof(ulong)) return (Enum)Enum.ToObject(a.GetType(), Convert.ToInt64(a) & Convert.ToInt64(b)); else return (Enum)Enum.ToObject(a.GetType(), Convert.ToUInt64(a) & Convert.ToUInt64(b)); } public static Enum Not(this Enum a) { // consider adding argument validation here return (Enum)Enum.ToObject(a.GetType(), ~Convert.ToInt64(a)); } }