在实现IEqualityComparer <t> .GetHashCode(T obj)时,我可以使用当前实例的状态,还是必须使用obj?</t>

时间:2014-07-25 04:34:12

标签: c# interface polymorphism

为什么我实现IEqualityComparer时,它有一个GetHashCode(T obj)的参数?当然,它不是静态对象,为什么我不能只使用当前实例的状态来生成哈希码?是this == obj吗?

我很好奇,因为我正在尝试这样做:

public abstract class BaseClass : IEqualityComparer<BaseClass>
{
    public abstract int GetHashCode(BaseClass obj);
}

public class DerivedClass : BaseClass
{
    public int MyData;

    public override int GetHashCode(BaseClass obj)
    {
        return MyData.GetHashCode();
        // Or do I have to do this:
        // return (DerivedClass)obj.MyData.GetHashCode();
    }
}

我正在尝试阻止进行演员,因为它被用于非常高性能的代码中。

2 个答案:

答案 0 :(得分:4)

我认为这里的主要问题是您将IEqualityComparer<T>IEquatable<T>混为一谈。

IEquatable<T> 定义了一种方法,用于确定当前实例(this)是否等于同一类型的实例。换句话说,它用于测试objA.Equals(objB)。实现此接口时,建议您还覆盖GetHashCode()实例方法。

IEqualityComparer<T> 定义了测试给定类型的两个对象是否相等的方法,换句话说,它是用于测试comparer.Equals(objA, objB)的方法。因此,有必要将对象作为参数提供给GetHashCode(记住,它与GetHashCode继承的object不同)

你可以认为IEquatable<T>是你的对象的说法,&#34; 这就是我知道如果我等于别的东西,&#34 ;和IEqualityComparer<T>作为对象的说法,&#34; 这就是我知道其他两件事情是否相等&#34;。

有关如何在框架中使用这两个接口的一些很好的示例,请参阅:

您是否应该使用IEqualityComparer<T>的当前状态来确定哈希码?如果状态完全可变,那么不!使用哈希的任何地方(例如HashSet<T>Dictionary<T, V>)哈希码将被缓存并用于高效查找。如果该哈希码可能因比较器的状态发生变化而发生变化,那将完全破坏存储哈希的数据结构的有用性。现在,如果状态不可变(即它只在创建比较器时设置并且在比较器的整个生命周期内都不能被修改),那么是的,你可以,但我仍然建议不要使用它,除非你有一个很好的理由。

最后,你提到了表现。老实说,这听起来像premature optimization。在您可以确定此特定代码行导致问题之前,我建议您不要过多担心性能问题。

答案 1 :(得分:1)

如果您没有使用传递obj参数的信息,那么您的哈希码对于不同的传入对象不会有所不同,并且没有用处。 Comparer 不是要获取哈希代码或与之比较的对象实例。

实际上,您可以在GetHashCode中使用comaprer的本地字段,甚至可以将MyData作为哈希代码返回,如示例中所示 - 它仍然满足GetHashCode要求&#34;返回相同对象的相同值数据&#34;。但是在你的示例中,所有哈希码对于比较器都是相同的,因此将它用于Dictionary将基本上将字典转换为列表。

这同样适用于Equals来电 - 确实你可以一直返回true,但它会有多大用处?