C#中重载相等(==)运算符示例
运算符重载一直是一个很诡异事情,因为在写代码的时候,不知道某个运算符有没有被重载过。在C++里面,运算符重载可以写在类的外面,当intellisense不工作的时候,找到一个运算符的重载函数是一件相当头疼的事情。这个问题在C#中改善了不少,因为运算符重载一定要写在类内,而且intellisense很强大。不过另一个问题又产生了……
先来看C++中的“==”重载:
structA{
intx;
inty;
};
inline
booloperator==(constA&a,constA&b){
returna.x==b.x&&a.y==b.y;
}
上面这段代码中,由于声明的关系,a和b永远不可能为NULL,所以直接调用a.x和b.x是没有问题的。
而在C#中:
structA
{
publicintx,y;
publicstaticbooloperator==(Aa,Ab)
{
returna.x==b.x&&a.y==b.y;
}
publicstaticbooloperator!=(Aa,Ab)
{
return!(a==b);
}
}
这段代码是没问题的,因为A是struct,而struct不可能为null。但换成class就有问题了,比如:
classA
{
publicintx,y;
publicstaticbooloperator==(Aa,Ab)
{
if(a==null&&b==null)
{
returntrue;
}
if(a==null||b==null)
{
returnfalse;
}
returna.x==b.x&&a.y==b.y;
}
publicstaticbooloperator!=(Aa,Ab)
{
return!(a==b);
}
}
由于referencetype可以为null,所以要先检查a和b是不是null,但是“a==null”这一句又会去调用“operator==”,于是就无限递归下去了……想了很久都没想出来变通的方法,而且System.String的实现也很诡异:
publicstaticbooloperator==(stringa,stringb)
{
returnEquals(a,b);
}
publicstaticboolEquals(stringa,stringb)
{
return((a==b)||(((a!=null)&&(b!=null))&&EqualsHelper(a,b)));
}
看上去也会无限递归的(Reflector出来的,不一定准),很神奇……
虽然对于Referecetype不建议重载==,但是不建议并不代表不能用吧,这个设计太挫了…