【问题标题】:x. Equals(null) returns false (for non-nullable value types only)X。 Equals(null) 返回 false(仅适用于不可为空的值类型)
【发布时间】:2019-03-17 09:07:15
【问题描述】:

在阅读 this article 时,我看到 Object.Equals 覆盖应该返回 false 如果仅为非可空值调用 null 参数:

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

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

【问题讨论】:

  • 没有什么说 object.Equals(null) 不应该为可为空的类型返回 false ,它只是暗示不能保证这样的结果(即不能依赖,即使理想情况下人们通常会期望这是案子)。但是,该示例对于可空类型是正确且首选的。对于不可为空的值类型,保证是正确的 - 没有矛盾,只是不同的情况。

标签: c# equality msdn


【解决方案1】:

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

对于class 类型,您在public bool Equals 非静态方法中,“this”永远不会是null,因此只要p 参数返回false 是正确的是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 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'!

【讨论】:

    【解决方案2】:

    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);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-16
      • 1970-01-01
      • 2014-02-07
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      相关资源
      最近更新 更多