字典键存在时找不到它
本文关键字:找不到 存在 字典 | 更新日期: 2023-09-27 18:11:36
为什么我的字典说一个键不存在,当我刚刚插入它?是我的Equals
方法还是双重比较?
代码如下:
// Test: I know the dictionary contains nCoord but its saying the key doesn't exist
Dictionary<UTMCoordinate, int> planes = new Dictionary<UTMCoordinate, int>();
UTMCoordinate nCoord = new UTMCoordinate(337394.136407966, 6263820.40182064, 0, 56, UTMCoordinate.Hemisphere.H_SOUTHERN);
planes[nCoord] = 1;
bool exists = planes.ContainsKey(nCoord); // always returns false
我的UTMCoordinate
实现如下:
public class UTMCoordinate
{
public enum Hemisphere {H_NOTHERN, H_SOUTHERN};
public const double DIF_TOLERANCE = 0.0005;
public double x { get; set; }
public double y { get; set; }
public double elev { get; set; }
public uint UTMZone { get; set; }
public Hemisphere hemisphere { get; set; }
public UTMCoordinate(double x, double y, double elev=double.MinValue, uint utmZone=uint.MinValue, Hemisphere hemisphere=Hemisphere.H_SOUTHERN) {
this.x = x;
this.y = y;
this.elev = elev;
this.UTMZone = utmZone;
this.hemisphere = hemisphere;
}
public override int GetHashCode() {
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + x.GetHashCode();
hash = hash * 23 + y.GetHashCode();
hash = hash * 23 + elev.GetHashCode();
hash = hash * 23 + UTMZone.GetHashCode();
hash = hash * 23 + hemisphere.GetHashCode();
return hash;
}
}
public override bool Equals(object obj)
{
UTMCoordinate other = obj as UTMCoordinate;
if (other == null)
return false;
return double.Equals(x, other.x) && double.Equals(y, other.y) && double.Equals(elev, other.elev) && uint.Equals(UTMZone, other.UTMZone) && double.Equals(hemisphere, other.hemisphere);
}
}
编辑使用Daniel a . Whites的建议,我使用了不同的双重比较方法。不幸的是,它仍然没有识别密钥:
public override bool Equals(object obj)
{
//return base.Equals (obj);
UTMCoordinate other = obj as UTMCoordinate;
if (other == null)
return false;
//return double.Equals(x, other.x) && double.Equals(y, other.y) && double.Equals(elev, other.elev) && uint.Equals(UTMZone, other.UTMZone) && double.Equals(hemisphere, other.hemisphere);
return Math.Abs (x-other.x) <= DIF_TOLERANCE && Math.Abs (y-other.y) <= DIF_TOLERANCE && Math.Abs (elev-other.elev) <= DIF_TOLERANCE && uint.Equals(UTMZone, other.UTMZone) && hemisphere == other.hemisphere;
}
如果我从你的问题中取出你的代码:
Dictionary<UTMCoordinate, int> planes = new Dictionary<UTMCoordinate, int>();
UTMCoordinate nCoord = new UTMCoordinate(337394.136407966, 6263820.40182064, 0, 56, UTMCoordinate.Hemisphere.H_SOUTHERN);
planes[nCoord] = 1;
bool exists = planes.ContainsKey(nCoord);
我得到的exists
的值是true
。
但是,如果我这样做:
nCoord.x = 1.0;
exists = planes.ContainsKey(nCoord);
exists
的值突然变成了false
,即使对象仍然在字典中。这是因为GetHashCode
的值发生了变化。原来是-1473667404
,但是在赋值了属性x
之后,它变成了201352392
。
字典使用GetHashCode
的值来确定将键放在哪个桶中,因此当哈希码更改时,字典可能会尝试在错误的桶中找到键,然后报告它不包含键。
我怀疑你的代码就是这样。
所以你需要改变你的对象,使它是不可变的
public double x { get; private set; }
public double y { get; private set; }
public double elev { get; private set; }
public uint UTMZone { get; private set; }
public Hemisphere hemisphere { get; private set; }