我有一个项目,我正在广泛使用通用的cdictionary。我需要组合键,所以我一直使用tuples作为键。在某种程度上,我想知道使用缓存哈希代码的自定义类是否有益:

public class CompositeKey<T1, T2> : Tuple<T1, T2>
{
    private readonly int _hashCode;

    public CompositeKey(T1 t1, T2 t2) : base(t1, t2)
    {
        _hashCode = base.GetHashCode();
    }

    public new int GetHashCode()
    {
        return _hashCode;
    }
}

我使用了new而不是override,因为我认为这对测试没有影响,因为我是使用具体类型定义字典的:
var dict = new Dictionary<CompositeKey<string, int>, int>();

然而,我注意到我的自定义GetHashCode方法根本没有被调用。当我将new更改为override时,它按预期被调用。
有人能解释为什么不调用隐藏的GetHashCode方法吗?如果我把字典定义成这样的话,我会预料到这种行为
var dict = new Dictionary<Tuple<string, int>, int>();

但如果像我的示例中那样显式地指定CompositeKey类型,则不会。
我知道隐藏GetHashCode方法可能不是个好主意。

最佳答案

有人能解释为什么不调用隐藏的gethashcode方法吗?
如果我把字典定义为

要调用CompositeKey.GetHashCode方法,必须在编译时将CompositeKey实例的引用键入CompositeKey
但是Dictionary<TKey,TValue>的代码库并不知道您的CompositeKey类(显然)。它所知道的是TKey(泛型类型参数),它与没有任何约束的System.Object等价。因为除了在T中声明的方法之外,您不能调用任何System.Object的方法,而没有约束。
所以,dictionary最终调用的Object.GetHashCode在类中不会被重写,因此它不会被调用。

09-11 03:47