如何检查包含的c ++ / cli ref项列表?

时间:2013-12-20 12:59:53

标签: c# c++-cli equals contains

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

2 个答案:

答案 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)

...我怀疑你会发现你的方法没有被调用。