Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 操作员'&';无法应用于类型为';T';和';T';_C#_Generics_Generic Method - Fatal编程技术网

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);
}