I have a class
public class Foo
{
public int ID { get; set; }
}
and I've implemented a LinqEqualityComparer to allow dynamic IEqualityComparer tests for the Except extenion method.
public class LinqEqualityComparer<T> : IEqualityComparer<T>
{
protected Func<T, T, bool> Comparison { get; set; }
public LinqEqualityComparer(Func<T, T, bool> comparison)
{
Comparison = comparison;
}
public bool Equals(T x, T y)
{
return Comparison(x, y);
}
public int GetHashCode(T obj)
{
return obj.GetHashCode();
}
}
I've created the following code to test it:
IEnumerable<Foo> settings = new Foo[]
{
new Foo{ID = 1},
new Foo{ID = 2}
};
IEnumerable<Foo> currentSettings = new Foo[]
{
new Foo{ID = 1},
new Foo{ID = 2},
new Foo{ID = 3}
};
IEqualityComparer<Foo> comparer = new LinqEqualityComparer<Foo>((x, y) => x.ID == y.ID);
IEnumerable<Foo> missing = currentSettings.Except(settings, comparer);
However Foos 1,2 and 3 are all present in the 'missing' variable.
Why does this LinqEqualityComparer not work?
Because your equality comparer does not implement GetHashCode
correctly. The GetHashCode
implementation must produce the same code for elements that compare equal. This does not happen here because the equality comparison is customized while the hash codes are not generated accordingly.
To make this work you would need to do one of two things:
Make the comparer accept the hash code implementation as an additional argument, i.e. x => x.ID.GetHashCode()
and forward to that. This is easiest and what you should do in practice.
Modify GetHashCode
in such a way that it is an aggregate function of the hash codes of the properties that take part in the comparison (here that is the ID
property) -- a straight xor of the individual hash codes would work (even though it might not be optiomal).
That leaves you with the problem of how to detect which
properties are compared. To be able to answer that question automatically you would need to accept an expression tree instead of a delegate for the comparison, i.e. an Expression<Func<T, T, bool>>
and then visit the expression tree to determine what to do. That's bound to not be easy going.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With