运算符'=='无法应用于类型T?

Che*_*hen 12 .net c# operator-overloading language-specifications

我认为这种方法有效,但我错了:

static void Equals<T>(T x, T y)
{
    return x == y;    //operator == can't be applied to type T
}
Run Code Online (Sandbox Code Playgroud)

在阅读了规范(v3.0中的第7.2.4节和v4.0中的第7.3.4节)之后:

7.2.4二元运算符重载决策

形式为x op y的操作,其中op是可重载的二元运算符,x是类型X的表达式,y是类型Y的表达式,按如下方式处理:

  • 由X和Y为操作运算符op(x,y)提供的候选用户定义运算符集合被确定.该集合由X提供的候选运算符和Y提供的候选运算符组合而成,每个运算符使用§7.2.5的规则确定.如果X和Y是相同类型,或者如果X和Y是从公共基类型派生的,则共享候选运算符仅出现在组合集中一次.

  • 如果候选用户定义的运算符集合不为空,则这将成为该操作的候选运算符集.否则,预定义的二元运算符op实现(包括它们的提升形式)将成为该操作的候选运算符集.给定运算符的预定义实现在运算符的描述中指定(第7.7节到第7.11节).

  • §7.4.3的重载决策规则应用于候选运算符集合,以根据参数列表(x,y)选择最佳运算符,并且此运算符成为重载解析过程的结果.如果重载解析无法选择单个最佳运算符,则会发生编译时错误.

在第2步中,我认为应该应用此预定义实现:

bool operator ==(object x, object y);
bool operator !=(object x, object y);
Run Code Online (Sandbox Code Playgroud)

因为C#中的所有内容都来自Object.如何在步骤3中发生编译时错误?在这种情况下,我不认为"重载决议无法选择".

编辑当我实现这样的事情时,我想到了这个问题:

class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
    public bool Equals(TEnum x, TEnum y)
    {
        return x == y;
    }
    public int GetHashCode(TEnum obj)
    {
        return (int)obj;
    }
}
Run Code Online (Sandbox Code Playgroud)

我担心我需要构建一个表达式并在Equals方法中动态调用它.

Eri*_*ert 20

阅读规范对你有好处,但你很快就停止了阅读.如果你进一步阅读,你会得到这一点:


预定义的引用类型相等运算符需要以下之一:

  • 两个操作数都是已知为引用类型或文字null的类型的值.此外,从操作数的类型到另一个操作数的类型存在显式引用转换.

  • 一个操作数是类型T的值,其中T是类型参数,另一个操作数是文字null.此外,T没有值类型约束.

除非其中一个条件成立,否则会发生绑定时错误.(*)


错误不是来自重载决策; 错误是重载决策将选择预定义的引用类型相等运算符,并且您没有引用类型.

考虑你的代码.是什么阻止T成为没有定义相等运算符的值类型?没有.假设我们回到了对象版本; 两个操作数都会包含在不同的位置,因此即使它们具有相同的内容,它们也是引用不相等的.由于这是缓慢,混乱和错误,甚至尝试也是违法的.

你为什么要在第一时间做这件事?如果你的方法不起作用,那么你的方法会比首先使用== 更糟糕.您打算使用此方法向世界添加的价值是多少?


(*)我已经向规范维护者报告了这句话中的语法错误.


Mar*_*ell 7

如果它知道这样where T : class做,那可能会有效,进行参考比较.运营商通常对泛型的支持很少,但有一些解决方法.MiscUtil为仿制药的运营商提供间接支持,否则EqualityComparer<T>.Default.Equals(x,y)是一个不错的选择.

  • @Danny - 然后尝试`EqualityComparer <T> .Default.Equals(x,y)` (4认同)