gpt4 book ai didi

C# 字典在键存在时抛出 KeyNotFoundException

转载 作者:行者123 更新时间:2023-12-03 20:50:38 24 4
gpt4 key购买 nike

我正在存储一个二维数组,它表示向量之间的距离矩阵作为 Dictionary<DistanceCell, double> .我的实现 DistanceCell有两个字符串字段代表被比较的向量。

class DistanceCell
{
public string Group1 { get; private set; }
public string Group2 { get; private set; }

public DistanceCell(string group1, string group2)
{
if (group1 == null)
{
throw new ArgumentNullException("group1");
}

if (group2 == null)
{
throw new ArgumentNullException("group2");
}

this.Group1 = group1;
this.Group2 = group2;
}
}

因为我使用这个类作为键,所以我覆盖了 Equals()GetHashCode() :

public override bool Equals(object obj)
{
// False if the object is null
if (obj == null)
{
return false;
}

// Try casting to a DistanceCell. If it fails, return false;
DistanceCell cell = obj as DistanceCell;
if (cell == null)
{
return false;
}

return (this.Group1 == cell.Group1 && this.Group2 == cell.Group2)
|| (this.Group1 == cell.Group2 && this.Group2 == cell.Group1);
}

public bool Equals(DistanceCell cell)
{
if (cell == null)
{
return false;
}

return (this.Group1 == cell.Group1 && this.Group2 == cell.Group2)
|| (this.Group1 == cell.Group2 && this.Group2 == cell.Group1);
}

public static bool operator ==(DistanceCell a, DistanceCell b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}

// If either is null, return false.
// Cast a and b to objects to check for null to avoid calling this operator method
// and causing an infinite loop.
if ((object)a == null || (object)b == null)
{
return false;
}

return (a.Group1 == b.Group1 && a.Group2 == b.Group2)
|| (a.Group1 == b.Group2 && a.Group2 == b.Group1);
}

public static bool operator !=(DistanceCell a, DistanceCell b)
{
return !(a == b);
}

public override int GetHashCode()
{
int hash;
unchecked
{
hash = Group1.GetHashCode() * Group2.GetHashCode();
}

return hash;
}

如您所见,DistanceCell 的要求之一是那个Group1Group2是可以互换的。所以对于两个字符串 xy , DistanceCell("x", "y")必须等于 DistanceCell("y", "x") .这就是我实现 GetHashCode() 的原因乘法因为DistanceCell("x", "y").GetHashCode()必须等于 DistanceCell("y", "x").GetHashCode() .

我遇到的问题是它在大约 90% 的时间内都可以正常工作,但会抛出 KeyNotFoundExceptionNullReferenceException剩下的时间。前者在从字典中获取键时抛出,后者在我使用 foreach 遍历字典时抛出。循环并检索一个为 null 的键,然后尝试调用 Equals()上。我怀疑这与我的 GetHashCode() 中的错误有关实现,但我不是积极的。另请注意,由于算法的性质,当我检查字典时,绝不会出现 key 不存在的情况。该算法每次执行都采用相同的路径。

更新

我只是想告诉大家这个问题已经解决了。事实证明,它与我的 Equals() 或 GetHashCode() 实现无关。我做了一些广泛的调试,发现我得到 KeyNotFoundException 的原因是因为字典中根本不存在该键,这很奇怪,因为我确信它被添加了。问题是我用多个线程将键添加到字典中,据此,c# Dictionary 类不是线程安全的。所以 Add() 失败的时机一定是完美的,因此 key 从未被添加到字典中。我相信这也可以解释 foreach 循环是如何偶尔产生一个空键的。来自多个线程的 Add() 一定弄乱了字典中的一些内部结构并引入了一个空键。

感谢大家的帮助!很抱歉,这完全是我的错。

最佳答案

看看this blog post作者:埃里克·利珀特

它表示即使更改对象的内容,GetHashCode 的结果也永远不会改变。原因是 Dictionary 使用桶来加快索引速度。更改 GetHasCode 结果后,Dictionary 将无法为您的对象找到正确的存储桶,这可能导致“找不到键”

我可能是错的,但值得测试。

关于C# 字典在键存在时抛出 KeyNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14428668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com