通用IEqualityComparer <T>和GetHashCode

对于实现大量的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);
    }
}

看起来不错,但是每次都提供散列函数是非常必要的? 我明白哈希码用于将对象放入桶中。 不同的桶,对象不相等,相等不被调用。

如果GetHashCode返回相同的值,则调用equals。 (来自:为什么当重写Equals方法时重写GetHashCode很重要?)

因此,如果例如(我听到很多程序员惊恐地尖叫)会出现什么问题,GetHashCode返回一个常量,以强制调用Equal?


没有什么会出错,但是在基于散列表的容器中,执行查找时,您将从大约O(1)到O(n)的性能。 你最好将所有内容都存储在一个列表中,并用蛮力搜索满足平等的项目。


如果一个常见的用例是根据它们的一个属性比较对象,那么可以添加一个额外的构造函数并实现,并像这样调用它:

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

这将自动使用该属性实现的散列。

编辑:更高效和更强大的实现激发了我的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); 

你的表现将会下降。 当在集合数据结构上实现时, DistinctExcept是有效的操作。 通过提供一个恒定的散列值,你基本上可以摧毁这个特性,并使用线性搜索来迫使朴素算法。

您需要查看这是否适用于您的数据量。 但对于较大的数据集,差异将会显着。 例如, Except预期的时间O(n)增加到O(n2)之外,这可能是一个大问题。

为什么不直接调用对象自己的GetHashCode方法而不是提供常量? 它可能不会给出特别好的值,但它不会比使用常量更差,并且除非对象的GetHashCode方法被重写以返回错误的值,否则正确性仍将保留。

链接地址: http://www.djcxy.com/p/85327.html

上一篇: Generic IEqualityComparer<T> and GetHashCode

下一篇: Using IEqualityComparer for Union