首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >等于实现,覆盖等于,IEquatable,==和!=

等于实现,覆盖等于,IEquatable,==和!=
EN

Stack Overflow用户
提问于 2021-06-02 12:51:39
回答 1查看 282关注 0票数 2

在C#中,我看到了许多关于平等以及如何实现平等的帖子和问题。我想尝试收集最佳实践,并提供一个解决方案,在没有重复代码的情况下或多或少没有样板代码。

从这样一个简单的类开始:

代码语言:javascript
复制
public class Foo
{
    public int Bar { get; set; }
}

我现在想在这个类中添加Equals调用的所有可能性,首先用ReSharper建议重写它:

代码语言:javascript
复制
public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != GetType()) return false;

    if(obj is Foo foo)
    {
        // here all the values should be checked
        return Bar == foo.Bar;
    }

    return false;
}

现在,我已经覆盖了相等调用,但是留给==!=运算符的是推荐https://www.loganfranken.com/blog/698/overriding-equals-in-c-part-3/

代码语言:javascript
复制
public static bool operator ==(Foo a, 
                               Foo b)
{
    if(ReferenceEquals(null, a)) return false; 
            
    return a.Equals(b); 
}

public static bool operator !=(Foo a,
                               Foo b)
{
    return !(a == b);
}

最后一步是像这样实现IEquatable<>接口,并调整覆盖Equals,使类保持如下所示:

代码语言:javascript
复制
public class Foo : IEquatable<Foo>
{
    public int Bar { get; set; }

    public bool Equals(Foo other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;

        // here all the values should be checked
        return Bar == other.Bar;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (obj.GetType() != GetType()) return false;

        return Equals(obj as Foo);
    }

    public static bool operator ==(Foo a,
                                   Foo b)
    {
        if(ReferenceEquals(null, a)) return false;
        
        return a.Equals(b);
    }

    public static bool operator !=(Foo a,
                                   Foo b)
    {
        return !(a == b);
    }
}

现在,在我看来,我已经或多或少地删除了所有重复的代码(不幸的是,我想不出一种方法来消除空检查)。我将在Equals(Foo other)方法中实现“核心逻辑”,其他的可以复制到任何其他类。

我在这里有什么陷阱或问题吗?或者推荐更少的代码?我并不是想获得最好的性能,清洁的代码应该是这个实现和其他类的可重用性的主要标准。那么,是否可以毫无问题地将最后3个方法复制到任何其他类,并且只在那里实现IEquatable<>并更改调用?

还请注意,我现在没有实现GetHashCode()

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-02 13:02:37

您不应该重复自己:实现public bool Equals(Foo other)就足够了;其他所有的:Equals==!=都可以从Equals(Foo other)派生出来。

代码语言:javascript
复制
public class Foo : IEquatable<Foo>
{
    public int Bar { get; set; }

    public bool Equals(Foo other)
    {
        if (ReferenceEquals(this, other)) return true;
 
        if (other is null) return false;

        // here all the values should be checked
        return Bar == other.Bar;
    }

    // Here we can put it short 
    public override bool Equals(object obj) => obj is Foo other && Equals(other);

    //TODO: Don't forget about hash 
    // Here I put the easiest approach which exploits the fact we
    // have just one property of type int. 
    public override int GetHashCode() => Bar;

    // Note ReferenceEquals(a, b): we want null == null be true
    public static bool operator == (Foo a, Foo b) =>
      ReferenceEquals(a, b) || (a is not null && a.Equals(b));

    public static bool operator !=(Foo a, Foo b) => !(a == b);
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67805459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档