在 IEquatable中实施是必要的参考检查

发布于 2024-10-11 13:25:01 字数 717 浏览 10 评论 0原文

我有一个实现 IEquatable 的类。是否有必要在 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);
    }

感谢您的回复。

I have a class that imlements IEquatable<T>. Is it necessary to do a refrence check in Equals() or is it taken care of in the framework?

class Foo : IEquatable<Foo>
{
    int value;
    Bar system;

    bool Equals(Foo other)
    {
        return this == other || 
        ( value == other.value && system.Equals(other.system) );
    }
}

In the above example is the this==other statement superfluous or necessary?

Update 1

I understand I need to correct the code as follows:

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

Thanks for the replies.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

染柒℉ 2024-10-18 13:25:01

这通常是一种优化 - 这将是一个奇怪的 Equals 实现,没有它就会失败。因此,我认为它是必要的 - 但它也没有“在框架中得到照顾”。 I 是一种成本低廉的优化,因此通常值得包含。

请注意,如果您还重载 ==,那么您可能应该使用 object.ReferenceEquals 来执行这些比较。

It's generally an optimization - it would be a strange Equals implementation which would fail without it. I would therefore not regard it as necessary - but nor does it it "taken care of in the framework". I's a cheap optimization to achieve, so it's usually worth including.

Note that if you're also overloading ==, then you should probably use object.ReferenceEquals to perform these comparisons.

挽清梦 2024-10-18 13:25:01

当心。我实际上强烈不鼓励这样做,因为如果您想根据Equals<重载您的Foo类型的==运算符/code> (正如我的经验中通常所做的那样)你会发现自己处于无限递归状态。

为了说明我的意思,这里是 ==Equals 方面的常见实现:

public static bool operator ==(Foo x, Foo y)
{
    // Will overflow the stack if Equals uses ==:
    return !ReferenceEquals(x, null) && x.Equals(y);
}

也就是说,我完全同意 Jon 的观点认为使用 ReferenceEquals 可能比较合适。

Be careful. I would actually strongly discourage this since if you ever want to overload the == operator for your Foo type in terms of Equals (as is usually done in my experience) you'll find yourself with an infinite recursion.

To illustrate what I mean, here is a common implementation of == in terms of Equals:

public static bool operator ==(Foo x, Foo y)
{
    // Will overflow the stack if Equals uses ==:
    return !ReferenceEquals(x, null) && x.Equals(y);
}

That said, I can wholeheartedly agree with Jon's point that it may be appropriate to use ReferenceEquals instead.

瀟灑尐姊 2024-10-18 13:25:01

它不是必要,因为它可能不需要正确性,但框架肯定不会“照顾它”,所以它可能放入,通常是出于性能原因。

一点:如果实现由 EqualityComparer.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;
}

题外话,您的示例方法中存在几个 null 取消引用问题(other 可能是 nullthis.system 可能是 )。

我会将您的方法编写为如下所示:

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

It's not necessary in the sense that it may not be required for correctness, but the framework certainly does not "take care of it", so it may be useful to put in, typically for performance reasons.

One point: if the implementation is wrapped by EqualityComparer<T>.Default, it doesn't enter the user code if one or both of the arguments are null, so in that case it does perform some measure of reference checking (if not a full 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;
}

Off-topic, there are several null-dereferencing issues in your sample method (other might be null, this.system might be null).

I would write your method as something like:

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.

}

Also remember to override GetHashCode whenever you write your own equality-comparisons.

感性 2024-10-18 13:25:01

我认为有必要检查this == other,因为你定义了自己的equals。如果您不希望对其进行指针检查,则可以编写自己的 IEquatable

I think it is necessary to check this == other, because you define your own equals. If you don't want it to be pointer-checked, you write your own IEquatable.

两相知 2024-10-18 13:25:01

IEquatable 是一个接口;实施由实施者决定。

由于您正在实现接口,因此您需要对接口定义的所有预期行为负责。

IEquatable<T> is an interface; the implementation is up to the implementer.

Since you are implementing the interface you are responsible for all expected behavior as defined by the interface.

素手挽清风 2024-10-18 13:25:01

我相信这是必要的。参考检查是比较对象时可以执行的第一个快速步骤。

在您给出的示例中,请务必在访问其值之前检查 other 是否不为 null。

bool Equals(Foo other)
{
    if(other == null) return false;

    if(this == other) return true;

    // Custom comparison logic here.
}

I believe that it's necessary. The reference check is the first, quick step you can perform when comparing objects.

In the example you have given, be sure to check that other is not null before accessing its values.

bool Equals(Foo other)
{
    if(other == null) return false;

    if(this == other) return true;

    // Custom comparison logic here.
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文