在IEquatable <t>实现中是必要的参考检查</t>

时间:2011-01-13 16:25:32

标签: c# equals iequatable

我有一个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语句是多余的还是必要的?

更新1

我知道我需要更正代码如下:

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

感谢您的回复。

6 个答案:

答案 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可能是nullthis.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.
}