代码之家  ›  专栏  ›  技术社区  ›  awmross

Delphi泛型集合是否覆盖equals?

  •  1
  • awmross  · 技术社区  · 14 年前

    我震惊地发现TList没有覆盖equals。看看这个例子:

    list1:=TList<String>.Create;       
    list2:=TList<String>.Create;
    
    list1.Add('Test');
    list2.Add('Test');
    
    Result:=list1.Equals(list2);
    

    “Result”为false,即使两个列表包含相同的数据。它使用默认的equals()(它只是比较两个引用的相等性)。

    从代码上看,对于所有其他泛型集合类型也是如此。

    如果试图在实践中使用TLists,这似乎是一个大问题。我该怎么办?我是否创建了自己的TBetterList来扩展TList并重写equals以做一些有用的事情?

    [编辑:到目前为止,我有一个答案,有很多赞成票,但它并没有真正告诉我我想知道什么。我将试着重新表述这个问题]

    在Java中,我可以做到:

    List<Person> list1=new ArrayList<Person>();
    List<Person> list2=new ArrayList<Person>();
    list1.add(person1);
    list2.add(person1);
    boolean result=list1.equals(list2);
    

    结果 是的 . 我不需要对任何东西进行子类化,它只起作用。

    如果我用Delphi写同样的代码, 结果 会结束的 假的。

    如果有一个解决方案只适用于对象,而不适用于字符串或整数,那么这也非常有用。

    3 回复  |  直到 14 年前
        1
  •  8
  •   Deltics    14 年前

    泛型与这个问题的关键不直接相关:选择什么构成一个有效的基本实现 测试完全是武断的。当前实施的 TList.Equals() 是一致的,至少会(我认为)VCL中所有其他类似的基类,我所说的相似不仅仅是指集合或泛型类。

    例如, TPersistent.Equals() 还做了一个简单的引用比较-它不比较任何已发布属性的值,这可以说是语义上等同于您所考虑的相等测试类型 列表 .

    你说的是延伸 TBetterList公司 在派生类中做一些有用的事情,就好像这是你的一项繁重的义务,但这正是面向对象软件开发的本质。

    等于() 可能与其他人的需求有很大的不同(或者在您自己的项目中,从一个基类派生的类到另一个基类)。

    所以,是的,然后由您实现对所提供基类的扩展,该扩展将反过来提供 新的 对您特别有用的基类。

    但这不是问题。

    这是一个机会。

    :)

        2
  •  3
  •   Kenneth Cochran    14 年前

    在Java(和.NET语言)中,所有类型都是从 Object TObject . 它们是本机类型,没有类定义。

    Equals 方法。所以编写 等于 只需遍历两个列表并调用 等于

    AbstractList Java 6 Open JDK中的定义:

    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof List))
            return false;
    
        ListIterator<E> e1 = listIterator();
        ListIterator e2 = ((List) o).listIterator();
        while(e1.hasNext() && e2.hasNext()) {
            E o1 = e1.next();
            Object o2 = e2.next();
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }
        return !(e1.hasNext() || e2.hasNext());
    }
    

    用于比较更复杂的对象。

    在Delphi中 T 不能保证是此默认实现的对象 等于 TObject.Equals

        3
  •  1
  •   awmross    14 年前

    我环顾四周,在DeHL(一个开源的Delphi库)中找到了一个解决方案。DeHL有一个Collections库,它有自己的可选列表实现。在向开发人员询问了这个问题之后,比较通用TLists的能力被添加到了当前不稳定的DeHL版本中。

    所以这段代码现在会给出我想要的结果(在Delphi中):

    list1:=TList<Person>.Create([Person.Create('Test')]);
    list2:=TList<Person>.Create([Person.Create('Test')]);
    
    PersonsEqual:=list1.Equals(list2); // equals true
    

    它适用于所有类型,包括字符串和整数类型

    stringList1:=TList<string>.Create(['Test']);
    stringList2:=TList<string>.Create(['Test']);
    
    StringsEqual:=stringList1.Equals(stringList2); // also equals true
    

    太好了!

    您需要查看最新的不稳定版本的DeHL(r497)才能使其正常工作。当前的稳定版本(0.8.4)具有与标准Delphi TList相同的行为。

    所以也许我会使用DeHL而不是标准的Delphi集合?这太可惜了,因为我更喜欢尽可能地使用标准平台库。我会更深入地研究戴尔。