Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Dictionary.GetKey返回False,即使键存在-GetHashCode/Equals已被重写_C#_Dictionary_Keynotfoundexception - Fatal编程技术网

C# Dictionary.GetKey返回False,即使键存在-GetHashCode/Equals已被重写

C# Dictionary.GetKey返回False,即使键存在-GetHashCode/Equals已被重写,c#,dictionary,keynotfoundexception,C#,Dictionary,Keynotfoundexception,这是C#。我有一个问题,Dictionary.ContainsKey返回false,即使我知道其中的键 不幸的是,我没有任何代码可以显示。代码不容易拼凑在一起;它分布在多个类中,并通过事件等触发。我编写的快速单元测试并没有重现这个问题 以下是调试会话期间立即窗口的输出(添加注释并更改以保护详细信息): 一些额外注意事项: 用作键的类型已重写GetHashCode和的方法 平等 字典被构造为新字典(),带有 没有额外的构造函数参数 通过调试,我已经验证了这一点 调用键类型中的GetHashCod

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

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

以下是调试会话期间立即窗口的输出(添加注释并更改以保护详细信息):

一些额外注意事项:

  • 用作键的类型已重写GetHashCode和的方法 平等
  • 字典被构造为新字典(),带有 没有额外的构造函数参数
  • 通过调试,我已经验证了这一点 调用键类型中的GetHashCode,但不调用Equals(obj)
  • 当 应用程序运行时,只有一个加载的DLL具有密钥类型, 因此,在不同的版本中,可能不是同一类型的情况 相同的DLL
有人知道为什么会这样吗

谢谢你的帮助,我的点子都快用完了

用作键的类型已重写GetHashCode和Equals的方法

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

发件人:

通常,对于可变引用类型,只有在以下情况下才应重写GetHashCode:

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

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

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


的确如果在对象存储在字典(或任何类似哈希表的结构)中时,对参与GetHashCode/Equality比较的属性进行变异,则会损坏字典并取消所有赌注。所有参与GetHashCode和Equality的属性都应该是不可变的。不要依赖文档进行此操作。谢谢。然而,考虑到上面的即时窗口的所有输出都是在应用程序处于断点时获取的,并且哈希代码是相同的,因此这似乎不太可能是问题所在。我遗漏了什么吗?@ck:字典损坏发生在断点之前,即,您在密钥进入字典后对其进行了变异,导致它生成与字典用于存储它的代码不同的代码。是的,您可以枚举密钥,但因为它们是针对不同的哈希代码存储的,所以您找不到它。@spender:说得对。为了测试这一点,我到达了同一个断点,然后在即时窗口中创建了一个MyKey实例,它使用的属性值与我期望字典中的键具有的属性值相同。即时窗口的新创建的键和字典中的键都具有相同的哈希代码。@ck:当然,但字典中的键在存储到字典中时是否具有相同的哈希代码?否则,密钥查找将失败,因为该项位于错误的哈希表存储桶中。
// 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