![](/img/trans.png)
[英]IEquatable<T> - Best practice override for .Equals(object obj) in C#
[英]Result of calling IEquatable<T>.Equals(T obj) when this == null and obj == null?
当this == null
和obj == 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;
}
空对象始终等于空对象。
示例代码在MSDN中: http : //msdn.microsoft.com/zh-cn/library/ms131190.aspx?ppud=4
如果this == null,您将在该对象上收到调用Equals()的运行时异常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.