我有一个imlements IEquatable<T>
的课程。是否有必要在Equals()
中进行参考检查,或者是否在框架中进行了检查?
class Foo : IEquatable<Foo>
{
int value;
Bar system;
bool Equals(Foo other)
{
return this == other ||
( value == other.value && system.Equals(other.system) );
}
}
在上面的示例中,this==other
语句是多余的还是必要的?
我知道我需要更正代码如下:
bool Equals(Foo other)
{
if( other==null ) { return false; }
if( object.ReferenceEquals(this, other) ) { return true; } //avoid recursion
return value == other.value && system.Equals(other.system);
}
感谢您的回复。
答案 0 :(得分:4)
这通常是一种优化 - 它将是一个奇怪的Equals
实现,没有它就会失败。因此,我不认为它是必要的 - 但也不是“在框架中照顾”。我是一个廉价的优化,所以它通常值得包括。
请注意,如果您也重载==
,那么您应该使用object.ReferenceEquals
来执行这些比较。
答案 1 :(得分:4)
小心点。我实际上强烈地阻止这个,因为如果你想要==
Foo
类型的Equals
运算符超载==
(通常在我的Equals
经验)你会发现自己的无限递归。
为了说明我的意思,这里是public static bool operator ==(Foo x, Foo y)
{
// Will overflow the stack if Equals uses ==:
return !ReferenceEquals(x, null) && x.Equals(y);
}
ReferenceEquals
的常见实现:
{{1}}
尽管如此,我可以全心全意地同意Jon's point使用{{1}}代替它。
答案 2 :(得分:1)
它不是必要的,因为它可能不是正确性所必需的,但框架当然不会“照顾它”,所以可能有用放入,通常是出于性能原因。
一点:如果实现由EqualityComparer<T>.Default
包装,如果其中一个或两个参数都是null
,它就不会输入用户代码,所以在这种情况下它确实执行了一些措施参考检查(如果不是完整的ReferenceEquals(x, y)
)。
public override bool Equals(T x, T y)
{
if (x != null)
{
return ((y != null) && x.Equals(y));
}
if (y != null)
{
return false;
}
return true;
}
偏离主题,您的示例方法中存在多个空的解除引用问题(other
可能是null
,this.system
可能是null
。
我会把你的方法写成:
public bool Equals(Foo other)
{
if(other == null)
return false;
if(other == this)
return true;
return value == other.value
&& EqualityComparer<Bar>.Default.Equals(bar, other.bar)
// You don't *have to* go down the EqualityComparer route
// but you do need to make sure you don't dereference null.
}
还记得在编写自己的相等比较时覆盖GetHashCode
。
答案 3 :(得分:0)
我认为有必要检查this == other
,因为您定义了自己的equals
。如果您不希望对其进行指针检查,则可以编写自己的IEquatable
。
答案 4 :(得分:0)
IEquatable<T>
是一个界面;实施取决于实施者。
由于您正在实现接口,因此您负责接口定义的所有预期行为。
答案 5 :(得分:-1)
我认为这是必要的。参考检查是比较对象时可以执行的第一个快速步骤。
在您提供的示例中,请务必在访问其值之前检查其他是否为空。
bool Equals(Foo other)
{
if(other == null) return false;
if(this == other) return true;
// Custom comparison logic here.
}