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

时间:2011-04-27 17:24:29

标签: c# .net operator-overloading language-specifications

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

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

阅读规范后(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来自a   公共基类型,然后共享   候选运营商只出现在   组合一次。

  •   
  • 如果设置的话   候选用户定义的运算符是   不是空的,那么这就变成了一套   候选人的经营者   操作。否则,预定义   二元运算符op实现,   包括他们提升的形式,成为   一组候选运营商   操作。预定义的   给定运算符的实现   在描述中指定   运营商(§7.7至§7.11)。

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

  •   

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

bool operator ==(object x, object y);
bool operator !=(object x, object y);

因为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;
    }
}

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

4 个答案:

答案 0 :(得分:20)

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


  

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

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

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

  •   
     

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


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

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

你为什么要首先尝试做这件事?如果你的方法奏效,它没有,那么你的方法是的更糟的比单纯使用==摆在首位。您打算使用此方法向世界添加什么值?


(*)我在这句话中向规范维护者报告了语法错误。

答案 1 :(得分:7)

如果知道where T : class进行参考比较,那可能会有效。运营商通常对泛型的支持很少,但有一些解决方法。 MiscUtil提供有关泛型的indirect support for operators,否则EqualityComparer<T>.Default.Equals(x,y)是一个不错的选择。

答案 2 :(得分:1)

我喜欢使用EqualityComparer<T>.Default

它基于重写的Equals方法,但在可用时使用IEquatable<T>,避免对实现它的值类型进行装箱。

EqualityComparer<T>.Default.Equals(x, y)

答案 3 :(得分:-1)

使用.Equals()方法并确保T实施IComparable