首页 文章

当此== null且obj == null时调用IEquatable <T> .Equals(T obj)的结果?

提问于
浏览
8

this == nullobj == null 时, IEquatable<T>.Equals(T obj) 应该怎么做?

1) 实现 IEquatable<T> 时,此代码由F#编译器生成 . 当两个对象都是 null 时,您可以看到它返回 true

public sealed override bool Equals(T obj)
    {
        if (this == null)
        {
            return obj == null;
        }
        if (obj == null)
        {
            return false;
        }

        // Code when both this and obj are not null.
    }

2) 类似代码可在“in IEquatable implementation is reference check necessary " or in the question " Is there a complete IEquatable implementation reference?”问题中找到 . 当两个对象都是 null 时,此代码返回 false .

public sealed override bool Equals(T obj)
    {
        if (obj == null)
        {
            return false;
        }

        // Code when obj is not null.
    }

3) 最后一个选项是说 this == null 时没有定义方法的行为 .

7 回答

  • 0

    F#这样做(我怀疑)将空列表优化为 null .

    通过添加此检查,它允许在没有任何问题的情况下在 null 实例上调用实例方法 .

    不久前见my blog post .

    在C#中,这是无关紧要的 .

    To answer the question:

    它应返回 true ,因为两个实例都是 null 并且视为相等 .

  • 0

    leppie是对的 . 只是详细说明他的答案(并确认他怀疑F#不保证 this != null) :有区别的联盟可能会用属性 [<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>] 标记,允许案例由值null表示.Option<'T>就是这样的类型. None 案例由在运行时为null . (None : option<int>).Equals(None) 在语法上是有效的 . 这是一个有趣的例子:

    [<CompilationRepresentation(CompilationRepresentationFlags.UseNullAsTrueValue)>]
    type Maybe<'T> =
      | Just of 'T
      | Nothing
      [<CompilationRepresentation(CompilationRepresentationFlags.Instance)>]
      member this.ThisIsNull() = match this with Nothing -> true | _ -> false
    

    用Reflector显示反编译 ThisIsNull

    public bool ThisIsNull()
    {
        return (this == null);
    }
    

    结果如下:

    Nothing.ThisIsNull() //true
    
  • 3

    如果 this 为null,则代码可以被考虑(无论如何,在C#中,有些情况下语言允许空对象具有解除引用的方法,但显然如果它在内部检查它的任何不存在的字段,它将会出错 . 考虑:

    return x.Equals(y);
    

    如果x为null,我们甚至不会调用 Equals 来进行空检查计数 .

    因此我们只需要考虑:

    public bool Equals(T obj)
    {
      if(obj == null)
        return false;
      //logic defining equality here.
    }
    

    如果我们从静态 == 运算符覆盖或 IEqualityComparer<T> 实现中检查它们,那么两个对象的可能性确实出现了:

    public bool Equals(T x, T y)
    {
      if(x == null)
        return y == null;
      if(y == null)
        return false;
      //logic defining equality here.
    }
    

    注意这里有一个有用的快捷方式,如果相等可以很长时间来确定(例如比较长字符串),那么我们可以利用身份需要平等的事实 - 即使Ayn Rand能够解决这个问题,这个问题总是等于它自己 . )还有一些算法可以使项目与自身进行比较非常普遍,这使得这个快捷方式非常值得包括 . 在这种情况下,身份比较已经包括检查两者都为null,所以我们再次将其保留:

    public bool Equals(T x, T y)
    {
      if(ReferenceEquals(x, y))
        return true;
      if(x == null || y == null)
        return false;
      //logic defining equality here.
    }
    
  • 9

    对于大多数方法,我在使用 this==null 调用时假设未定义的行为 . 这是因为大多数程序员在 this!=null 的假设下编写代码,如果调用代码是用C#编写的,则由C#规范保证 .

    这就是为什么 x.Equals(y) 的每个理智的调用者应该确定 x 不是 null ,或者添加一个手册 null 检查 .

    在大多数情况下,我根本不会直接调用 Equals ,而是使用 EqualityComparer<T>.Default .

  • 1

    我肯定会选择1:

    if (this == null)
        {
            return obj == null;
        }
        if (obj == null)
        {
            return false;
        }
    

    null对象始终等于null对象 .

  • 0
  • 1

    如果这= = null,您将获得一个在该对象上调用Equals()的运行时异常 .

相关问题