编写等于运算符时处理null的最佳方法
Possible Duplicate: How do I check for nulls in an '==' operator overload without infinite recursion?
当我为对象重载==运算符时,我通常会这样写:
public static bool operator ==(MyObject uq1, MyObject uq2) { if (((object)uq1 == null) || ((object)uq2 == null)) return false; return uq1.Field1 == uq2.Field1 && uq1.Field2 == uq2.Field2; }
如果我们不屈服于对象,那么函数会递归到自身中,但是我想知道是否有更好的方法?
解决方案
回答
ReferenceEquals(对象obj1,对象obj2)
回答
if ((object)uq1 == null) return ((object)uq2 == null) else if ((object)uq2 == null) return false; else //return normal comparison
当两者都为null时,这会将它们比较为相等。
回答
遵循DB处理:
null == <anything> is always false
回答
@ neouser99:这是正确的解决方案,但是遗漏的部分是,当重写相等运算符(运算符==)时,我们还应该重写Equals函数,并简单地使运算符调用该函数。并非所有.NET语言都支持运算符重载,因此,是覆盖Equals函数的原因。
回答
正如微软所说,
A common error in overloads of operator == is to use (a == b), (a == null), or (b == null) to check for reference equality. This instead results in a call to the overloaded operator ==, causing an infinite loop. Use ReferenceEquals or cast the type to Object, to avoid the loop.
因此,使用ReferenceEquals(a,null)|| ReferenceEquals(b,null)是一种可能性,但强制转换为对象也一样(我认为实际上是等效的)。
因此,是的,似乎应该有一种更好的方法,但是建议我们使用一种方法。
但是,正如已经指出的那样,在覆盖==时,我们实际上也应该覆盖Equals。使用LINQ提供程序以不同的语言编写并在运行时进行表达式解析,即使我们自己拥有所有代码,谁也知道不执行该操作的时间。
回答
但是,为什么不创建对象成员函数呢?当然,不能在Null引用上调用它,因此我们确定第一个参数不是Null。
确实,我们失去了二元运算符的对称性,但仍然...
(请注意Purfideas的答案:如果需要作为数组的前哨值,则Null可能等于Null)
还请考虑==函数的语义:有时我们确实希望能够选择是否测试
- 身份(指向同一对象)
- 价值平等
- 等价(例如1.000001等于.9999999)
回答
只需使用Resharper创建Equals和GetHashCode方法。为此,它将创建最全面的代码。
更新
我并不是故意发布它,而是让人们使用Resharper的功能而不是粘贴粘贴,因为代码在每个类之间都不同。关于开发Cwithout Resharper,伙计,我不了解你的生活。
无论如何,这是一个简单类的代码(由Resharper 3.0生成,我正在使用4.0的旧版本,我目前不记得它是否创建相同的代码)
public class Foo : IEquatable<Foo> { public static bool operator !=(Foo foo1, Foo foo2) { return !Equals(foo1, foo2); } public static bool operator ==(Foo foo1, Foo foo2) { return Equals(foo1, foo2); } public bool Equals(Foo foo) { if (foo == null) return false; return y == foo.y && x == foo.x; } public override bool Equals(object obj) { if (ReferenceEquals(this, obj)) return true; return Equals(obj as Foo); } public override int GetHashCode() { return y + 29*x; } private int y; private int x; }