嵌套对象上的 EqualityComparer

fil*_*lur 2 c#

我想比较两个嵌套对象列表。如果父对象Id不同和/或任何子对象IdBaz属性不同,我想认为它们已更改。

我已经实现了我自己的版本EqualsGetHashCode以下版本,但尽管使用了我自己的 equalcomparer,Except()仍然会产生结果,而我希望对象是相等的。

var foo1 = new Foo
{
    Id = 1,
    Bars = new List<Bar>
    {
        new Bar
        {
            Id = 1,
            Baz = 1.5
        },
        new Bar
        {
            Id = 1,
            Baz = 1.5
        }
    }
};

var foo2 = new Foo
{
    Id = 1,
    Bars = new List<Bar>
    {
        new Bar
        {
            Id = 1,
            Baz = 1.5
        },
        new Bar
        {
            Id = 1,
            Baz = 1.5
        }
    }
};

var diff = new[] { foo1 }.Except(new[] { foo2 });
Run Code Online (Sandbox Code Playgroud)
public class Foo
{
    private sealed class IdBarsEqualityComparer : IEqualityComparer<Foo>
    {
        public bool Equals(Foo x, Foo y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (ReferenceEquals(x, null)) return false;
            if (ReferenceEquals(y, null)) return false;
            if (x.GetType() != y.GetType()) return false;
            return x.Id == y.Id && Equals(x.Bars, y.Bars);
        }

        public int GetHashCode(Foo obj)
        {
            unchecked
            {
                return (obj.Id * 397) ^ (obj.Bars != null ? obj.Bars.GetHashCode() : 0);
            }
        }
    }

    public static IEqualityComparer<Foo> IdBarsComparer { get; } = new IdBarsEqualityComparer();

    public int Id { get; set; }
    public List<Bar> Bars { get; set; }
}

public class Bar
{
    protected bool Equals(Bar other)
    {
        return Id == other.Id && Baz.Equals(other.Baz);
    }

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

    public override int GetHashCode()
    {
        unchecked
        {
            return (Id * 397) ^ Baz.GetHashCode();
        }
    }

    public int Id { get; set; }
    public double Baz { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Sel*_*enç 5

您的代码中有三处错误:

  1. 您没有将相等比较器传递给Except方法,因此它没有被使用。
  2. 您的GetHashCode实现Foo是错误的,它对相同的对象返回不同的结果,因此Equals永远不会调用该方法。
  3. 您在两个列表上调用 equals: Equals(x.Bars, y.Bars),这会检查引用是否相等。您可以使用SequenceEqual以下方法来一一比较元素:x.Bars.SequenceEqual(y.Bars)