对于实现大量的IEqualityComparers有些懒惰,并且考虑到我无法轻松编辑被比较对象的类实现,我使用了以下内容,意味着与Distinct()和Except()扩展方法一起使用.:
public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
Func<T, T, bool> compareFunction;
Func<T, int> hashFunction;
public GenericEqualityComparer(Func<T, T, bool> compareFunction, Func<T, int> hashFunction)
{
this.compareFunction = compareFunction;
this.hashFunction = hashFunction;
}
public bool Equals(T x, T y)
{
return compareFunction(x, y);
}
public int GetHashCode(T obj)
{
return hashFunction(obj);
}
}
Run Code Online (Sandbox Code Playgroud)
看起来不错,但每次真的需要一个哈希函数?我知道哈希码用于将对象放入存储桶中.不同的桶,对象不相等,并且不调用相等.
如果GetHashCode返回相同的值,则调用equals.(来自:为什么在重写Equals方法时重写GetHashCode很重要?)
那么可能出现什么问题,例如(我听到很多程序员惊恐地尖叫),GetHashCode返回一个常量,强制调用Equal?
如果一个常见的用例是根据它们的一个属性比较对象,你可以添加一个额外的构造函数并实现并调用它,如下所示:
public GenericEqualityComparer(Func<T, object> projection)
{
compareFunction = (t1, t2) => projection(t1).Equals(projection(t2));
hashFunction = t => projection(t).GetHashCode();
}
var comaparer = new GenericEqualityComparer( o => o.PropertyToCompare);
Run Code Online (Sandbox Code Playgroud)
这将自动使用属性实现的哈希.
编辑:一个更有效和更强大的实现启发了我的Marc评论:
public static GenericEqualityComparer<T> Create<TValue>(Func<T, TValue> projection)
{
return new GenericEqualityComparer<T>(
(t1, t2) => EqualityComparer<TValue>.Default.Equals( projection(t1), projection(t2)),
t => EqualityComparer<TValue>.Default.GetHashCode(projection(t)));
}
var comparer = GenericEqualityComparer<YourObjectType>.Create( o => o.PropertyToCompare);
Run Code Online (Sandbox Code Playgroud)