为了账号安全,请及时绑定邮箱和手机立即绑定

列出自定义类的相等性

列出自定义类的相等性

C#
至尊宝的传说 2023-05-14 16:10:34
我有一个类A,它包含一个字符串属性并覆盖Equals以进行相等性测试。public class A{    public string Prop { get; }    public A(string val)    {        Prop = val;    }    public override bool Equals(object obj)    {        return obj is A arg && (Prop == arg.Prop);    }    public override int GetHashCode()    {        return base.GetHashCode();    }}我还有一个B具有List<A>as 属性的类:public class B{    public IReadOnlyList<A> Prop { get; }    public B(IReadOnlyList<A> val)    {        Prop = val;    }    public override bool Equals(object obj)    {        // ...    }    public override int GetHashCode()    {        return base.GetHashCode();    }}我希望能够与 B 的实例进行比较以获得平等和秩序。如何通过不重写我在 A 中编写的相同代码来在 B 中编写 Equals 方法?有没有办法重用 A Equals?
查看完整描述

4 回答

?
HUWWW

TA贡献1874条经验 获得超12个赞

更新:我假设的第一个版本B是从A.

  1. A.Equals:

如果A未密封,obj is A ...则比较不同类型时可能会返回误报。所以更正后的版本:

public override bool Equals(object obj){
    return obj is A other
        && this.Prop == other.Prop
        && this.GetType() == other.GetType(); // not needed if A is sealed}
  1. A.GetHashCode:

base.GetHashCode将为不同但相等的实例返回不同的哈希码,这是错误的。改为从自身属性派生哈希码。如果Prop表现得像一些 ID,则只需返回Prop.GetHashCode()

  1. B.Equals:

    public override bool Equals(object obj)
    {      
      return obj is B other
            && this.Prop.SequenceEqual(other.Prop) // will re-use A.Equals
            && this.Prop.GetType() == other.Prop.GetType() // not needed if different IReadOnlyList types are ok
            && this.GetType() == other.GetType(); // not needed if B is sealed
    }
  1. B.GetHashCode:

您可以聚合实例的哈希码A。这里我使用了一个简单的 XOR,但如果相同的项目经常以不同的顺序出现,你可以想出更奇特的东西。

return Prop.Aggregate(0, (h, i) => h ^ i.GetHashCode());


查看完整回答
反对 回复 2023-05-14
?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

可以通过使用方法(来自命名空间)来实现Equals列表,它确保一个列表中的每个项目都等于另一个列表中同一索引处的项目。SequenceEqualsSystem.Linq

然而,您可能会考虑改变的一件事是您对GetHashCode. 如果两个项目相等,此方法应返回相同的数字(尽管不能保证具有相同哈希码的两个项目相等)。使用base.GetHashCode()不满足这个要求,因为在这种情况下base是;object根据文档,“引用类型的哈希码是通过调用基类的 Object.GetHashCode 方法计算的,该方法根据对象的引用计算哈希码”,因此对象仅在引用确切的对象时返回相同的 HashCode同一个对象。

应该HashCode基于用于确定相等性的相同属性,因此在这种情况下我们要使用Prop.GetHashCode()for class A,并且我们想要聚合Propfor class中所有项目的哈希码B

这是重构类的一种方法:

public class A : IEquatable<A>

{

    public string Prop { get; }


    public A(string val)

    {

        Prop = val;

    }


    public bool Equals(A other)

    {

        if (other == null) return false;

        return Prop == other.Prop;

    }


    public override bool Equals(object obj)

    {

        return Equals(obj as A);

    }


    public override int GetHashCode()

    {

        return Prop.GetHashCode();

    }

}


public class B : IEquatable<B>

{

    public IReadOnlyList<A> Prop { get; }


    public B(IReadOnlyList<A> val)

    {

        Prop = val;

    }


    public bool Equals(B other)

    {

        if (other == null) return false;

        if (ReferenceEquals(this, other)) return true;

        if (Prop == null) return other.Prop == null;

        return other.Prop != null && Prop.SequenceEqual(other.Prop);

    }


    public override bool Equals(object obj)

    {

        return Equals(obj as B);

    }


    public override int GetHashCode()

    {

        return Prop?.Aggregate(17,

            (current, item) => current * 17 + item?.GetHashCode() ?? 0)

                ?? 0;

    }

}


查看完整回答
反对 回复 2023-05-14
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

Linq 包含一个有用的方法来比较集合:SequenceEqual

public override bool Equals(object obj)

{

    if (!(obj is B other))

    {

        return false;

    }


    if (this.Prop == null || other.Prop == null)

    {

        return false;

    }


    return this.Prop.SequenceEqual(other.Prop);

}

此外,IEquatable<T>在覆盖 Equals 时实施。


查看完整回答
反对 回复 2023-05-14
?
忽然笑

TA贡献1806条经验 获得超5个赞

这样的事情怎么样:


public override bool Equals(object obj)

{

    if(!(obj is B))

    {

        return false;

    }


    var b = obj as B;


    if(b.Prop.Count != this.Prop.Count)

    {

        return false;

    }


    for(var i =0; i < Prop.Count; i++)

    {

        if (!Prop.ElementAt(i).Equals(b.Prop.ElementAt(i)))

        {

            return false;

        }

    }


    return true;

}


查看完整回答
反对 回复 2023-05-14
  • 4 回答
  • 0 关注
  • 148 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信