繁体   English   中英

调用IEquatable的结果 <T> .quals(T obj)当此== null和obj == null吗?

[英]Result of calling IEquatable<T>.Equals(T obj) when this == null and obj == null?

this == nullobj == null时, IEquatable<T>.Equals(T obj)IEquatable<T>.Equals(T obj)

1)该代码由F#编译器在实现IEquatable<T>时生成。 您可以看到当两个对象都为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)类似的代码可以在“ 在IEquatable实现中必须进行引用检查的问题”或“ 是否有完整的IEquatable实现参考? ”问题中找到。 当两个对象均为null时,此代码返回false

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

        // Code when obj is not null.
    }

3)最后一个选择是说当this == null时,未定义方法的行为。

嬉皮是对的。 只是为了详细说明他的答案(并确认他对F#不能保证做到this != null)怀疑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

F#这样做的原因(我怀疑)是为了将空列表优化为null

通过添加此检查,它允许一个人在null实例上调用实例方法而没有任何问题。

不久后可以看到我的博客文章

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

要回答这个问题:

由于两个实例均为null且被视为相等,因此它应返回true

如果this是空,代码不能被调用,所以这种情况下,不必考虑(在C#中,无论如何,存在以下情况:语言允许有一种方法解除引用一个空的对象,虽然很明显,如果它在内部检查任何非-existent字段将出错。

return x.Equals(y);

如果x为null,我们甚至都不会调用Equals来计算null检查。

因此,我们只需要考虑:

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也可以弄清楚这一点; )还有一些算法可以使项目与自身的比较非常普遍,因此值得一并包括此快捷方式。 在这种情况下,身份比较已经包含了两者均为空的检查,因此我们将其省略:

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

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

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

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

我肯定会选择选项1:

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

空对象始终等于空对象。

如果this == null,您将在该对象上收到调用Equals()的运行时异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM