代码之家  ›  专栏  ›  技术社区  ›  Dimitri C.

在泛型函数中使用重载运算符==

  •  12
  • Dimitri C.  · 技术社区  · 16 年前

    请考虑以下代码:

    class CustomClass
    {
        public CustomClass(string value)
            { m_value = value; }
    
        public static bool operator ==(CustomClass a, CustomClass b)
            { return a.m_value == b.m_value; }
    
        public static bool operator !=(CustomClass a, CustomClass b)
            { return a.m_value != b.m_value; }
    
        public override bool Equals(object o)
            { return m_value == (o as CustomClass).m_value; }
    
        public override int GetHashCode()
            { return 0; /* not needed */ }
    
        string m_value;
    }
    
    class G
    {
        public static bool enericFunction1<T>(T a1, T a2) where T : class
            { return a1.Equals(a2); }
        public static bool enericFunction2<T>(T a1, T a2) where T : class
            { return a1==a2; }
    }
    

    现在当我调用这两个泛型函数时, 一个成功,一个失败 :

    var a = new CustomClass("same value");
    var b = new CustomClass("same value");
    Debug.Assert(G.enericFunction1(a, b)); // Succeeds
    Debug.Assert(G.enericFunction2(a, b)); // Fails
    

    显然,g.enericFunction2执行默认运算符==implementation而不是my override。有人能解释为什么会这样吗?

    2 回复  |  直到 16 年前
        1
  •  15
  •   prostynick    16 年前

    Constraints on Type Parameters (C# Programming Guide) :

    当应用where t:class约束时,请避免使用==和!=类型参数上的运算符,因为这些运算符只测试引用标识,而不测试值相等性。即使在用作参数的类型中重载了这些运算符,也会出现这种情况。(…)这种行为的原因是,在编译时,编译器只知道t是引用类型,因此必须使用对所有引用类型都有效的默认运算符。

        2
  •  0
  •   Petar Minchev    16 年前

    如果我改变 enericFunction2 到:

        public static bool enericFunction2<T>(T a1, T a2) where T : class
        {
            object aa = a1;
            CustomClass obj1 = (CustomClass)aa;
    
            object bb = a2;
            CustomClass obj2 = (CustomClass)bb;
    
            return obj1 == obj2; 
        }
    

    然后一切正常。但恐怕我无法解释。我的意思是 a1 a2 了解他们的类型。为什么需要一个演员 CustomClass ,那么操作员被调用了?