C# 操作员'&';无法应用于类型为';T';和';T';
我的应用程序定义了几个C# 操作员'&';无法应用于类型为';T';和';T';,c#,generics,generic-method,C#,Generics,Generic Method,我的应用程序定义了几个enums,其中包括[Flags]属性 我想编写一个小实用程序方法来检查是否为那些enums中的任何一个设置了标志,我提出了以下建议 protected static bool IsFlagSet<T>(ref T value, ref T flags) { return ((value & flags) == flags); } protected static bool IsFlagSet(参考T值,参考T标志) { 返回((值和标志)=标
enum
s,其中包括[Flags]
属性
我想编写一个小实用程序方法来检查是否为那些enum
s中的任何一个设置了标志,我提出了以下建议
protected static bool IsFlagSet<T>(ref T value, ref T flags)
{
return ((value & flags) == flags);
}
protected static bool IsFlagSet(参考T值,参考T标志)
{
返回((值和标志)=标志);
}
但这给了我一个错误“运算符'&'不能应用于'T'和'T'类型的操作数”
这可以正常工作吗?Enum类已经有一个实用函数:
Enum.HasFlag(标志f)
,请参阅
注:这是在C#4中引入的。
虽然它可读性很强,但可能存在一些性能问题 &是类类型上的运算符。这意味着类T必须有一个重载运算符的方法& Net不能期望每个类都有它。所以它失败了 您可以做的是创建一个基类,将操作符重载声明为方法 然后使用声明T使用该基类:
protected static bool IsFlagSet<T> where T: BaseclassWithAnd (ref T value, ref T flags)
{
return ((value & flags) == flags);
}
protectedstatic bool IsFlagSet,其中T:BaseclassWithAnd(ref T value,ref T flags)
{
返回((值和标志)=标志);
}
您必须将其类型转换为定义操作的类型(&O)
protected static bool IsFlagSet<T>(ref T value, ref T flags)
{
return ((Convert.ToInt32(value) & Convert.ToInt32(flags)) == Convert.ToInt32(flags));
}
protected static bool IsFlagSet(参考T值,参考T标志)
{
返回((Convert.ToInt32(值)和Convert.ToInt32(标志))==Convert.ToInt32(标志));
}
错误的原因是您不能将泛型类型限制为“为t,t定义运算符X”。结果C#必须假设没有为T定义运算符X,T并显示错误
这是经常讨论的与==运算符相关的行为-即,但适用于所有运算符
有关可能的约束的完整列表,请参见-,请注意,对于Enum(这对您的场景特别有用)或定义了运算符X的类型,都没有约束。我知道我的答案太晚了,但我发现这个问题的解决方案非常令人惊讶。 从.NET4开始,我们可以在C#中使用
动态类型。您可以重写该方法:
protected static bool IsFlagSet<T>(T value, T flags)
{
dynamic a = value;
dynamic b = flags;
return ((a & b) == flags);
}
protected static bool IsFlagSet(T值,T标志)
{
动态a=数值;
动态b=标志;
返回((a&b)=标志);
}
若类型T
支持方法/运算符,则dynamic
背后的思想允许您推迟到运行时。因此,如果为T
定义了&
,那么运行时就是成功的。不需要那些ref
修饰符。好吧,好吧。在示例中使用了它们。我假设它们可以有效地处理大值类型。枚举永远不会大到足以使其成为优化。在Swap()中,它们是功能性的。+1谢谢,我错过了这一次,将使用它代替我原来的方法。但是,我觉得我应该接受一个更具体地回答我的问题的答案。+1-如果可以使用.Net 4,请使用Enum.hassflag。0@Alexei:啊,是.NET4.0的新版本吗?这就解释了我怎么会错过它。(他们为什么不在代码中添加<代码> SET旗舰()/代码>?)阿列克谢:你是对的,我看了,它也被列为FX 3.5,但这可能是一个错误。注意<代码> HasFlag <代码>是使用反射实现的,所以考虑任何可能的性能影响。我如何定义一个带有操作符重载的接口?我认为你不能在接口中定义操作符,只能在类中定义。但我可能错了,我的坏,不能用静态方法做接口。不过,您可以创建一个基类。另一个选项是创建一个可以从模板调用的方法和()。枚举不是类,我认为你不能让它编译/工作。要让它工作,你需要声明其中t:Enum
作为类型约束,但这是不受支持的-对于这种情况,甚至有一个特定的C#编译器错误消息。
protected static bool IsFlagSet<T>(T value, T flags)
{
dynamic a = value;
dynamic b = flags;
return ((a & b) == flags);
}