C# 为所有枚举添加扩展方法,而不仅仅是特定类型的枚举
编辑:这篇文章不是重复的,其他解决方案不允许我使用位运算符 我想这样做:C# 为所有枚举添加扩展方法,而不仅仅是特定类型的枚举,c#,generics,enums,constraints,extension-methods,C#,Generics,Enums,Constraints,Extension Methods,编辑:这篇文章不是重复的,其他解决方案不允许我使用位运算符 我想这样做: public static class EnumExt { public static enum AddFlag(this enum e, enum flag) => e |= flag; } 所以我可以这样使用它: Color color = Red; color.AddFlag(Color.Dark); 它只是更容易阅读。我希望这个单一方法适用于所有枚举值,而不是对我计划使用的每个枚举值进行重写。问题
public static class EnumExt
{
public static enum AddFlag(this enum e, enum flag) => e |= flag;
}
所以我可以这样使用它:
Color color = Red;
color.AddFlag(Color.Dark);
它只是更容易阅读。我希望这个单一方法适用于所有枚举值,而不是对我计划使用的每个枚举值进行重写。问题是,该代码不起作用,因为enum
的类型与int
的类型不同。我试着用泛型做一些事情:
public static class EnumExt
{
public static T AddFlag<T>(this T e, T flag)
where T : Enum // Can't constrain to Enum
{
return e = e | flag;
}
}
我的猜测是,即使这些限制仅限于Enum
值,其他类仍有可能从IEnumConstraint
和IConvertible
继承,因此按位运算符将不起作用,因为它仍然不能保证操作对t
可用
看起来唯一真正的解决方案是在C#7.3中,它们允许您使用
System.Enum
作为约束。能够解决这个问题。我必须从T
转换到object
,然后转换到int
,对int
值使用位运算符,然后将其反转以返回结果
@mjwills指出,C#7.3不会解决铸造问题。它将修复的只是约束,我将能够删除抛出异常
public static T AddFlag<T>(this ref T e, T flag)
where T : struct, IConvertible
{
if (!(typeof(T).IsEnum)) throw new ArgumentException("Value must be an enum");
int added = (int)(object)e | (int)(object)flag;
e = (T)(object)added;
return e;
}
public static T AddFlag(此ref T e,T标志)
其中T:struct,IConvertible
{
如果(!(typeof(T).IsEnum))抛出新的ArgumentException(“值必须是枚举”);
int added=(int)(object)e |(int)(object)标志;
e=(T)(对象)已添加;
返回e;
}
您安装了哪个版本的VS 2017可能存在重复?这是最新的预览吗?可能的副本有帮助吗?
// Doesn't work because C# won't allow bitwise operators on generic types
// Because the constraint is still vague enough for non-enum values to slip through
public static T AddFlag<T>(this T e, T flag)
where T : struct, IConvertible
// Doesn't work because enums don't inherit from IEnumConstraint
// Same as above
public static T AddFlag<T>(this T e, T flag)
where T : struct, IEnumConstraint
public static T AddFlag<T>(this ref T e, T flag)
where T : struct, IConvertible
{
if (!(typeof(T).IsEnum)) throw new ArgumentException("Value must be an enum");
int added = (int)(object)e | (int)(object)flag;
e = (T)(object)added;
return e;
}