X。 Equals(null) returns false(仅适用于不可为 null 的值类型)

x. Equals(null) returns false (for non-nullable value types only)

在阅读 this article 时,我看到 Object.Equals 重写应该 return false 如果仅针对不可为 null 的值调用 null 参数:

同时我阅读了给定的示例 - TwoDPoint - 是一个可为空的类型,但它与指南本身相矛盾。

那么,为可空类型重载 Equals 方法的最佳实践是什么?

TwoDPoint - is a nullable type

不,TwoDPoint 不是可空类型,Nullable Type 应该包含一个问号:

TwoDPoint? 是可空类型,它是 shorthand for 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);

TwoDPoint 是一个 class 类型,它是一个引用类型。因此,允许使用特殊值 null 作为参考。因此 TwoDPoint 类型的值 p 可能是 null.

对于 class 类型,在 public bool Equals 非静态方法中,“this”永远不会 null,因此它是正确的return 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 value 类型 的特殊 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 reference。 "null" 是 Nullable<TimeSpan> 结构的一个值,它的 HasValue 属性 等于 falseEquals 方法在 Nullable<> 中声明(在本例中作为覆盖),因此不会发生装箱。

不同:

// Example 5
var t = (TimeSpan?)null;
var type = t.GetType(); // 'GetType' declared in class (System.Object), boxing, 'NullReferenceException'!