C#比较两个泛型值

92
可能重复:
在C#中,泛型类型不能应用运算符==吗?

我编写了这样的代码:

public bool IsDataChanged()
{           
    T value1 = GetValue2;
    T value2 = GetValue1();

    return (valueInDB != valueFromView);
}

现在这个函数无法编译,错误提示为“运算符'!='不能应用于类型为'T'和'T'的操作数”。我该怎么做才能使这个函数正常工作?


2
无法在C#中将运算符应用于泛型类型的副本 - Jay Bazuzi
2
请问如何比较同一未受限制的泛型类型的两个元素是否相等?可以参考https://dev59.com/rXRC5IYBdhLWcg3wUvQS。 - Sean Bright
4个回答

166

如果没有添加 where T : class 指示它是引用类型,那么对于泛型类型不能使用运算符(除了特殊情况 foo == null),这时你需要使用 EqualityComparer<T>.Default。但对于只提供 == 运算符重载而不实现 IEquatable<T> 或重写 object.Equals() 的类型来说,这种方法将无法生效。

通常来说,仅实现 == 运算符而不至少做其中一项的处理是极为糟糕的想法,因此这不太可能成为一个问题。

public bool IsDataChanged<T>()
{           
    T value1 = GetValue2;
    T value2 = GetValue1();

    return !EqualityComparer<T>.Default.Equals(value1 , value2);
}

如果你没有限制为IEquatable<T>,那么当值类型没有实现IEquatable<T>时,EqualityComparer默认回退可能会导致装箱(如果你控制正在使用的类型,则可能并不重要)。我假设你之前使用=!是为了性能,所以限制为泛型类型将避免通过Object.Equals(object)路线产生意外的装箱。


9
实际上,您不需要使用 T:IEquatable<T> 的限制 - 它可以在没有该限制的情况下工作,使用 .Equals 方法即可。 - Marc Gravell
感谢提供运算符链接,但我觉得值得指出的是,你不能直接使用这些运算符,你必须通过某种方式来实现相同的行为。MiscUtils中的方法就是非常好的解决方式 :) 我指出了保持限制的原因,即使你不必这样做。 - ShuggyCoUk
抱歉,但是推理是不正确的;约束条件 不必要的,而且是个负担。 - Marc Gravell
不需要更正你是对的,我会进行编辑以使其更清晰明确。 - ShuggyCoUk
value1和value2不应该是valueInDB和valueFromView吗? - Shane Courtrille

9
那应该适合你的需求。
public bool test<T>(T test, T test2) where T : class
{
    return (test != test2);
}

这只是从评论您问题的示例中简单复制粘贴而来。


即使被采纳的答案更完整,这个解决方案肯定是解决问题最容易的一个。 - Monsieur Max
5
这只检查了 Object.ReferenceEquals(test, test2),而没有检查值相等性。 - Nick Strupat
我可以在 Razor 组件中使用此选项,通过以下方式定义组件:@typeparam TValue where TValue : class。 - Santiago
那个 where T: class 真的清理了我在泛型周围使用的很多烦人的样板文件,非常方便! - Ecksters

5

您的类型需要实现 IComparableIEquatable 接口。

可能您需要将 a!=b 重写为 !(a==b),或者显式调用 CompareTo() 或 Equals() 方法。


1
您可以在对象上重载.Equals()方法并更改评估方式:
return (!valueInDB.Equals(valueFromView));

假设valueInDB和valueFromView是对象。您的示例变量与比较中使用的变量名称不同,因此我必须假设。

编辑:被打败了3秒!关于重载的说明,如果您需要在类型内比较值,则来自Object类的基本.Equals()将不足够,因为它只会对复杂类型进行内存比较。您需要重载并提供您想要比较对象的实现。


注意空引用异常。 - Joseph Lennox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接