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; }
}
 
    