TStringList - 奇怪的行为

5

Delphi 1是16位的(是的,它很老,但它很好用)

一些示例代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  SL: TStringList;
begin

  SL := TStringList.Create;
  SL.Sorted := True;
  SL.Duplicates := dupIgnore;

  SL.AddObject('A', TObject(100));
  SL.AddObject('A', TObject(999));
  ShowMessage(IntToStr(LongInt(SL.Objects[0]))); {A}

  SL.Free;

end;

我使用对象字段来存储长整数(这是一种hack,但它可以完成工作)。无论如何,在上面的A行,我希望ShowMessage显示100,但实际上它显示999(即使设置了dupIgnore)。我错过了什么吗?或者它应该按照这种方式工作(我希望字符串列表忽略999)?

2个回答

6

刚在Delphi 2009中进行了测试-它显示100(根据Delphi 2009关于Duplicates和dupIgnore的文档,它应该显示100)。

可能这是Delphi 1的一个错误。


更新

@Sertac Akyuz:是的,这似乎是真的。谷歌显示旧版本的Delphi有以下TStringList.Add和TStringList.AddObject方法的实现:

function TStringList.Add(const S: string): integer;
begin
  if not Sorted then
    Result := FCount
  else
    if Find(S, Result) then
      case Duplicates of
        dupIgnore: Exit;
        dupError: Error(SDuplicateString, 0);
      end;
  InsertItem(Result, S);
end;

function TStrings.AddObject(const S: string; AObject: TObject): Integer;
begin
  Result := Add(S);
  PutObject(Result, AObject);
end;

当前(Delphi 2009)的实现方式是:

function TStringList.Add(const S: string): Integer;
begin
  Result := AddObject(S, nil);
end;

function TStringList.AddObject(const S: string; AObject: TObject): Integer;
begin
  if not Sorted then
    Result := FCount
  else
    if Find(S, Result) then
      case Duplicates of
        dupIgnore: Exit;
        dupError: Error(@SDuplicateString, 0);
      end;
  InsertItem(Result, S, AObject);
end;

看到区别了吗?旧实现可能被视为错误(如内存泄漏等)或未经记录的允许行为。无论如何,当前实现已摆脱了这个问题。


Delphi XE的文档并没有提及此事。它只说重复的字符串会被忽略,但并未说明与重复字符串相对应的对象会发生什么。 - Rob Kennedy
@Rob Kennedy - dupIgnore 阻止尝试将重复的字符串(带或不带对象)添加到排序列表中。在这种情况下,返回的索引并不重要 - 字符串不会被添加到列表中。 - kludg
Rob没有谈论字符串 - 它肯定没有被添加。他谈论的是与重复字符串相关联的对象。文档没有说明对象会发生什么。在早期版本的Delphi中,虽然未添加重复字符串,但与其关联的对象将替换先前的对象。这应该被视为一种设计选择,而不是一个错误,可能是一个糟糕的选择,因为它们改变了它(我看到有人在2004年投诉,所以行为可能在D7之后改变)。 - Sertac Akyuz
查看Add/AddObject的源代码就可以清楚地看到。这可能不是最好的设计选择。我最终添加了一个SL.IndexOf('A')调用。它解决了问题,但也增加了更多的代码。感谢大家的评论。 - FrankCM

3

你没有错过任何东西。这就是发生的事情。

AddObject 首先调用 Add,返回列表中新元素(或现有元素)的索引。然后它调用 PutObject,将对象值分配给该索引。文档未指定与 Duplicates 属性相关的行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接