3

这是在 C# 中。我有一个问题,即 Dictionary.ContainsKey 返回 false,即使我知道密钥在其中。

不幸的是,我没有任何代码可以显示。代码不容易拉到一起;它分布在多个类中,并通过事件等触发。我写的一个快速单元测试没有重现这个问题。

这是调试会话期间即时窗口的输出(添加注释并更改以保护细节):

// throws KeyNotFoundException
myDict[key]  

// throws KeyNotFoundException
myDict[new MyKey("SomeString .1", "SomeOtherString", SomeEnum.Foo)]

// Element [5] is the key
myDict.Keys
Count = 10
    [0]: {...}
    [1]: {...}
    [2]: {...}
    [3]: {...}
    [4]: {...}
    [5]: {Foo SomeOtherString SomeString  .1}
    [6]: {...}
    [7]: {...}
    [8]: {...}
    [9]: {...}

// Get key at element [5]   
enumerator.Current
{Foo SomeOtherString SomeString  .1}
    [My.Namespace.KeyType]: {Foo SomeOtherString SomeString  .1}
    SomeEnum: Foo
    SomeOtherStringProperty: "SomeOtherString"

// key used to do lookup
key
{Foo SomeOtherString SomeString  .1}
    [My.Namespace.KeyType]: {Foo SomeOtherString SomeString  .1}
    SomeEnum: Foo
    SomeOtherStringProperty: "SomeOtherString"

// hash codes of key in dictionary matches hash code of lookup key
enumerator.Current.GetHashCode()
193014103
key.GetHashCode()
193014103

一些额外的说明:

  • 用作键的类型具有覆盖 GetHashCode 和 Equals 的方法。
  • 字典被构造为 new Dictionary() ,没有额外的构造函数参数。
  • 通过调试,我已经验证了键类型中的 GetHashCode 被调用,而不是 Equals(obj)
  • 当应用程序运行时,只加载了一个具有密钥类型的 DLL,因此在同一个 DLL 的不同版本中可能不是相同类型的情况

有谁知道为什么会发生这种情况?

感谢您的帮助-我的想法已经不多了。

4

1 回答 1

4

用作键的类型具有覆盖 GetHashCode 和 Equals 的方法。

这是我要检查的第一件事。如果哈希码基于可变值,则肯定会导致此问题。

来自MSDN

一般来说,对于可变引用类型,只有在以下情况下才应该覆盖 GetHashCode:

  • 您可以从不可变的字段计算哈希码;或者

  • 您可以确保当对象包含在依赖于其哈希码的集合中时,可变对象的哈希码不会改变。

否则,您可能会认为可变对象在哈希表中丢失了。如果您确实选择为可变引用类型覆盖 GetHashCode,则您的文档应明确指出,当对象存储在哈希表中时,您的类型的用户不应修改对象值。

于 2014-09-10T00:48:03.733 回答