在阅读this article时,我看到Object.Equals覆盖应该返回false,如果仅为非可空值调用null参数:
同时我读到给定的例子 - TwoDPoint - 是一个可以为空的类型,但它与指南本身相矛盾。
那么,为可空类型重载Equals方法的最佳实践是什么呢?
TwoDPoint
是class
类型,是参考类型。因此,允许特殊值null
作为参考。所以p
类型的值TwoDPoint
可能是null
。
使用class
类型,你在public bool Equals
非静态方法中,“this
”永远不是null
,因此每当false
参数是p
时返回null
是正确的。
// Example 1
var t = new Point(10, 4);
var p = (Point)null;
var isEqual = t.Eqauls(p); // should return 'false', therefore the code you ask about
// Example 2
var t = (Point)null;
var p = (Point)null;
var isEqual = t.Eqauls(p); // 'NullReferenceException', method not called
在上面,您可以看到它对参考类型的作用。
使用用于可空值类型的特殊Nullable<>
类型,事情有点不同。但是好消息是你不必编写Nullable<>.Equals
的代码,因为它已经在.NET Framework中了。
// Example 3
var t = (TimeSpan?)TimeSpan.FromHours(3.5);
var p = (TimeSpan?)null;
var isEqual = t.Equals(p); // will return 'false'
// Example 4
var t = (TimeSpan?)null;
var p = (TimeSpan?)null;
var isEqual = t.Equals(p); // OK, method will return 'true'!
在示例4中,不发生空引用。存在的“null”是Nullable<TimeSpan>
结构的值,其HasValue
属性等于false
。在Equals
中声明了Nullable<>
方法(在本例中为覆盖),因此不会发生装箱。
不同:
// Example 5
var t = (TimeSpan?)null;
var type = t.GetType(); // 'GetType' declared in class (System.Object), boxing, 'NullReferenceException'!
TwoDPoint - 是一个可以为空的类型
不,TwoDPoint
不是可以为空的类型,Nullable Type应该包含一个问号:
TwoDPoint?
是一个可以为空的类型,它是Nullable<TwoDPoint>
的简写
因此,如果您在可空类型上调用Equals
,它将不会调用覆盖/重载方法。
TwoDPoint? a = new TwoDPoint();
var b = (TwoDPoint)a;
// call Nullable<TwoDPoint>.Equals, not TwoDPoint.Equals
a.Equals(b);
// call TwoDPoint.Equals
b.Equals(b);