I would like to compare two list of nested objects. If the parent objects Id
differ and/or any of the childrens Id
or Baz
property differs, I want to consider them changed.
I've implemented my own version of Equals
and GetHashCode
below, but despite using my own equalitycomparer, Except()
still yields a result, while I expect the objects to be equal.
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 });
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; }
}