请考虑以下代码:
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执行默认的operator ==实现而不是我的覆盖。任何人都能解释为什么会这样吗?
答案 0 :(得分:15)
来自Constraints on Type Parameters (C# Programming Guide):
当应用where T:class约束时,请避免使用type参数上的==和!=运算符,因为这些运算符将仅测试引用标识,而不是值相等。即使这些运算符在用作参数的类型中重载,也是如此。 (...)这种行为的原因是,在编译时,编译器只知道T是引用类型,因此必须使用对所有引用类型都有效的默认运算符。
答案 1 :(得分: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;
}
然后一切正常。但我恐怕无法解释。我的意思是a1
和a2
知道他们的类型。为什么需要对CustomClass
进行强制转换,因此调用运算符?