猿问

列出自定义类的相等性

我有一个类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?


至尊宝的传说
浏览 149回答 4
4回答

HUWWW

更新:我假设的第一个版本B是从A.A.Equals:如果A未密封,obj is A ...则比较不同类型时可能会返回误报。所以更正后的版本:public&nbsp;override&nbsp;bool&nbsp;Equals(object&nbsp;obj){ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;obj&nbsp;is&nbsp;A&nbsp;other &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;this.Prop&nbsp;==&nbsp;other.Prop &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;this.GetType()&nbsp;==&nbsp;other.GetType();&nbsp;//&nbsp;not&nbsp;needed&nbsp;if&nbsp;A&nbsp;is&nbsp;sealed}A.GetHashCode:base.GetHashCode将为不同但相等的实例返回不同的哈希码,这是错误的。改为从自身属性派生哈希码。如果Prop表现得像一些 ID,则只需返回Prop.GetHashCode()B.Equals:&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;override&nbsp;bool&nbsp;Equals(object&nbsp;obj) &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;obj&nbsp;is&nbsp;B&nbsp;other &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;this.Prop.SequenceEqual(other.Prop)&nbsp;//&nbsp;will&nbsp;re-use&nbsp;A.Equals &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;this.Prop.GetType()&nbsp;==&nbsp;other.Prop.GetType()&nbsp;//&nbsp;not&nbsp;needed&nbsp;if&nbsp;different&nbsp;IReadOnlyList&nbsp;types&nbsp;are&nbsp;ok &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&&&nbsp;this.GetType()&nbsp;==&nbsp;other.GetType();&nbsp;//&nbsp;not&nbsp;needed&nbsp;if&nbsp;B&nbsp;is&nbsp;sealed &nbsp;&nbsp;&nbsp;&nbsp;}B.GetHashCode:您可以聚合实例的哈希码A。这里我使用了一个简单的 XOR,但如果相同的项目经常以不同的顺序出现,你可以想出更奇特的东西。return&nbsp;Prop.Aggregate(0,&nbsp;(h,&nbsp;i)&nbsp;=>&nbsp;h&nbsp;^&nbsp;i.GetHashCode());

牧羊人nacy

可以通过使用方法(来自命名空间)来实现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;    }}

慕妹3242003

Linq 包含一个有用的方法来比较集合:SequenceEqualpublic 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 时实施。

忽然笑

这样的事情怎么样:public override bool Equals(object obj){&nbsp; &nbsp; if(!(obj is B))&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; var b = obj as B;&nbsp; &nbsp; if(b.Prop.Count != this.Prop.Count)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; }&nbsp; &nbsp; for(var i =0; i < Prop.Count; i++)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (!Prop.ElementAt(i).Equals(b.Prop.ElementAt(i)))&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return true;}
随时随地看视频慕课网APP
我要回答