我有一个类型Relation
,它会覆盖GetHashCode
和Equals
。
/// <see cref="System.Object.Equals"/>
public override bool Equals(object obj)
{
bool equals = false;
if (obj is Relation)
{
Relation relation = (Relation)obj;
equals = name.Equals(relation.name);
}
return equals;
}
/// <see cref="System.Object.GetHashCode"/>
public override int GetHashCode()
{
return name.GetHashCode();
}
我有两个Relation
个对象relation1
和relation2
。
我有一个名为HashSet<Relation>
的{{1}}。
relations
以下代码段应输出HashSet<Relation> relations = new HashSet<Relation>();
relations.Add(relation1);
和relation1
的哈希码。
relation2
输出结果为:
HashSet<Relation>.Enumerator enumerator = relations.GetEnumerator();
enumerator.MoveNext();
Console.WriteLine(relations.Comparer.GetHashCode(enumerator.Current));
Console.WriteLine(relations.Comparer.GetHashCode(relation2));
以下代码段比较134042217
134042217
和relation1
是否相等。
relation2
输出结果为:
Console.WriteLine(relations.Comparer.Equals(enumerator.Current, relation2));
但是,当我尝试确定hashSet是否包含True
时,我得到了意外的结果。
relation2
输出结果为:
relations.Contains(relation2)
我希望False
。
以下是我从MSDN中了解到的内容:为了确定元素的存在,True
应首先调用Contains
然后调用GetHashCode
。如果两个方法都返回Equals
,那么就会有匹配。
答案 0 :(得分:4)
如果在将第一个对象插入HashSet后更改Name
,则会发生这种情况。
HashSet记录了对象的原始哈希码,它与第二个对象不同。
答案 1 :(得分:1)
我写了一个测试程序,其中包含你的替代。
internal class Relation
{
public string Name { get; set; }
public override bool Equals(object obj)
{
bool equals = false;
if (obj is Relation)
{
Relation relation = (Relation)obj;
equals = Name.Equals(relation.Name);
}
return equals;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
var relation1 = new Relation() {Name = "Bob"};
var relation2 = new Relation {Name = "Bob"};
var relations = new HashSet<Relation>();
relations.Add(relation1);
var does = relations.Contains(relation2);
// does is now true
}
}
因此,在最小的情况下,您的代码可以满足您的期望。因此,我建议在进行relation1
检查时,导致relation2
和Contains
不相同的其他内容会发生。
答案 2 :(得分:0)
根据您的摘要,我写了以下完整示例:
class Program
{
static void Main(string[] args)
{
var r1 = new Relation("name");
var r2 = new Relation("name");
HashSet<Relation> r = new HashSet<Relation>();
r.Add(r1);
bool test = r.Contains(r2);
}
}
class Relation
{
public readonly string Name;
public Relation(string name)
{
Name = name;
}
public override bool Equals(object obj)
{
bool equals = false;
if (obj is Relation)
{
Relation relation = (Relation)obj;
equals = Name.Equals(relation.Name);
}
return equals;
}
/// <see cref="System.Object.GetHashCode"/>
public override int GetHashCode()
{
return Name.GetHashCode();
}
}
'test'的值为true。我可以解释代码与此示例之间行为差异的唯一方法是,在执行包含检查时,两个对象之间的Name属性不能相同。