2010-05-27 104 views
12

考虑下面的代码:在泛型函数重载使用运算符==

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执行默认的运算符==实现,而不是我的覆盖。有谁能解释为什么会发生这种情况?

+0

说'a1.Equals(a2)'调用**虚拟**实例方法。即使重载是在编译时固定的(对于System.Object.Equals(System.Object)),在运行时它总是被重载的方法被调用。这就是虚拟方法的全部内容。说'a1 == a2'调用一个'static'方法(至少在形式上存在一个方法'public static bool operator ==(object x,object y){...}')。调用'=='的重载在编译时是固定的,并且由于'T'不受限于匹配自定义'=='的东西,编译器可以选择的唯一东西就是'object' version == '。 – 2013-01-05 19:04:34

回答

15

Constraints on Type Parameters (C# Programming Guide)

当将其中T:类约束,避免==和=对类型参数运营商,因为这些运算符将测试对于参考身份只,不为值相等!。即使这些运算符在用作参数的类型中被重载,情况也是如此。 (...)这种行为的原因是,在编译时,编译器只知道T是引用类型,因此必须使用对所有引用类型都有效的默认运算符。

0

如果我改变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; 
    } 

然后一切工作正常。但我恐怕我无法解释它。我的意思是a1a2知道他们的类型。为什么CustomClass需要演员阵容,因此调用操作员?

+0

谢谢,但我想使用泛型类型而不是固定类型的CustomClass。 – 2010-05-27 09:47:46