c ++ / cli ref class DataEntity
实现了Equals和HashCode。我可以通过以下方式检查Equals
实现的行为:
entity1.Equals(entity2);
(C#source),它可以正常工作。
如果我现在有一个这样的DataEntities列表,我在该列表上调用Contains(entity)
,则永远不会调用Equals方法。
是什么原因,以及如何正确使用List.Contains(...)方法?
根据MSDN documentation,方法Contains(...)调用Equals(...)
示例:
C ++ / CLI来源:
public ref class DataEntity : System::Object
{
public:
DataEntity(System::String^ name,
System::String^ val)
: m_csName(name),
m_csValue(val) {}
System::String^ GetName() { return m_csName; }
System::String^ GetValue() { return m_csValue; }
virtual bool Equals(Object^ obj) new {
if(!obj){
return false;
}
DataEntity^ other = (DataEntity^)obj;
if(other){
if(m_csName->Equals(other->m_csName) &&
m_csValue->Equals(other->m_csValue)){
return true;
}
return false;
}
return false;
}
virtual int GetHashCode() new {
const int iPrime = 17;
long iResult = 1;
iResult = iPrime * iResult + m_csName->GetHashCode();
iResult = iPrime * iResult + m_csValue->GetHashCode();
return iPrime;
}
private:
System::String^ m_csName;
System::String^ m_csValue;
};
C#来源:
DataEntity entity1 = new DataEntity("Name", "Value");
DataEntity entity2 = new DataEntity("Name", "Value");
Console.WriteLine("Entities 1&2 are Equal: " + entity1.Equals(entity2));
List<DataEntity> entities = new List<DataEntity>();
entities.Add(entity2);
Console.WriteLine("ListContains_Entity2: " + entities.Contains(entity2));
输出:
Entities 1&2 are Equal: True
ListContains_Entity2: False
答案 0 :(得分:3)
virtual int GetHashCode() new
你的错误。您编写了一个隐藏Object :: GetHashCode的GetHashCode 替换。它不覆盖方法。 List :: Contains方法知道有关替换的bean,它仍然调用Object :: GetHashCode()。它将很快结束,因为所有这些对象都有不同的哈希代码,无需继续寻找相等性。你用Equals()犯了同样的错误。
您必须在此处使用override
关键字:
virtual bool Equals(Object^ obj) override {
// etc...
}
virtual int GetHashCode() override {
// etc...
}
小心使用 new 这样的关键字。它仅用于一个目的,当它认为你通过隐藏基本方法做错时,它会抑制编译器的强烈警告。该警告在90%的时间内是准确的,当基本方法是虚拟时为99%。
答案 1 :(得分:1)
我的猜测是你实现了这样的重载:
public bool Equals(DataEntity entity)
Contains
将调用 。但是,如果您覆盖Equals(object)
中声明的System.Object
方法,则将被调用。
这可以解释这两种症状,因为
entity1.Equals(entity2)
将使用你的超载。要在使用Object
中声明的方法时检查它是否有效,只需使用:
entity1.Equals((object) entity2)
...我怀疑你会发现你的方法没有被调用。