我想使用ConcurrentDictionary
检查之前是否已添加此数据密钥,但看起来我仍然可以添加之前添加的密钥。
代码:
public class pKeys
{
public pKeys()
{ }
public pKeys(long sID, long pID)
{
this.seID = sID;
this.pgID = pID;
}
public long seID;
public long pgID;
}
public static ConcurrentDictionary<pKeys, bool> existenceDic
= new ConcurrentDictionary<pKeys, bool>();
测试代码:
pKeys temKey = new pKeys(111, 222);
bool res = existenceDic.TryAdd(temKey, true);
Console.WriteLine(res);
temKey = new pKeys(111, 222);
res = existenceDic.TryAdd(temKey, true);
Console.WriteLine(res);
结果:
true
true
答案 0 :(得分:3)
您可以添加两个包含相同值的不同实例,因为您没有覆盖GetHashCode()
和Equals()
。这会导致使用默认的相等比较,对于引用类型,只需比较引用本身。在这种情况下,两个不同的实例始终被视为不同的值。
一种选择是将您的类型设为struct
而不是class
。这使用默认比较,该比较将考虑字段值。
或者,您可以继续覆盖GetHashCode()
和Equals()
。例如:
public class pKeys
{
public pKeys()
{ }
public pKeys(long sID, long pID)
{
this.seID = sID;
this.pgID = pID;
}
public readonly long seID;
public readonly long pgID;
public override int GetHashCode()
{
return seID.GetHashCode() * 37 + pgID.GetHashCode();
}
public override bool Equals(object other)
{
pKeys otherKeys = other as pKeys;
return otherKeys != null &&
this.seID == otherKeys.seID &&
this.pgID == otherKeys.pgID;
}
}
注意:
readonly
。如果您决定将类型设为struct
(即使您不重写方法),这将是 critical 。但是即使对于一个类来说,可变类型也是一个很大的问题,因为如果它们在添加到基于散列的集合后发生变化,则该集合实际上已被破坏。在此处使用readonly
可确保类型不可变。 (此外,应避免使用恕我直言公共领域,但如果必须拥有它们,即使您不重写相等方法,它们也应该是readonly
。Equals()
方法中检查确切的类型相等。事实上,这通常是一个好主意......它简化了比较对象的场景,并使代码更易于维护。但是为了举例,可分配性(即as
)更容易阅读,并且无论如何在许多情况下都是有效的。有关其他指导,请参阅General advice and guidelines on how to properly override object.GetHashCode()。