3

我正在尝试以下代码来创建不区分大小写的 IList:

procedure TForm1.ListButtonClick(Sender: TObject);
var
  MyList: IList<string>;
begin
  MyList := TCollections.CreateList<string>(TStringComparer.OrdinalIgnoreCase());
  MyList.AddRange(['AAA', 'BBB', 'CCC']);
  Memo1.Lines.Add(MyList.IndexOf('aaa').ToString);
end;

但是 IndexOf 调用总是返回 -1。这应该工作吗?任何建议表示赞赏。

更新:看起来比较器用于排序,但不是用于 IndexOf。IndexOf使用了一个单独的“EqualityComparer”,那么问题就变成了如何改变它?

Update2:我只是想添加到 Johan 的答案中,然后可以像这样创建列表:

MyCIList := TCaseInsensitiveList<string>.Create(
  TStringComparer.OrdinalIgnoreCase(),
  TStringComparer.OrdinalIgnoreCase());
4

2 回答 2

2

此问题已在 Spring4D 修补程序 1.2.1 中解决。通过更改,以下代码按预期工作。

procedure TForm1.ListButtonClick(Sender: TObject);
var
  MyList: IList<string>;
begin
  MyList := TCollections.CreateList<string>(TStringComparer.OrdinalIgnoreCase());
  MyList.AddRange(['AAA', 'BBB', 'CCC']);
  Memo1.Lines.Add(MyList.IndexOf('aaa').ToString);  // Correctly returns 0.
end;
于 2017-05-22T16:44:03.167 回答
1

IndexOf 的代码如下所示:

function TList<T>.IndexOf(const item: T; index, count: Integer): Integer;
begin
  Result := TArray.IndexOf<T>(fItems, item, index, count, EqualityComparer);
end;

EqualityComparer 是一个调用 GetEqualityComparer 的属性,如下所示:

protected
  class function GetEqualityComparer: IEqualityComparer<T>; static;

static意味着该方法不能在子类中被覆盖。

您需要编辑 Spring 的源代码并进行以下更改:

Spring.Collections.Base

103:   TEnumerableBase<T> = class abstract(TEnumerableBase, IEnumerable<T>)
106:   protected
108:   class var fEqualityComparer: IEqualityComparer<T>;  
//     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//Move this line from private to the protected section.
.......

                                                                ^^^^^^^^

现在您可以像这样创建自己的TCaseInsensitiveList

type
  TCaseInsensitiveList<T> = class(Spring.Collections.TList<T>)
    constructor Create(const Comparer: IComparer<T>; 
                       const EqualityComparer: IEqualityComparer<T>);
  end;
  .....
constructor TCaseInsensitiveList<T>.Create(
             const Comparer: IComparer<T>; 
             const EqualityComparer: IEqualityComparer<T>);
begin
  inherited Create(Comparer);
  Self.fEqualityComparer:= EqualityComparer;
end;

或者,您可以将基GetEqualityComparer类函数声明为虚拟并在子类中覆盖它。

制作虚拟是有成本的GetEqualityComparer,这就是为什么我选择让底层类变量受保护的原因。

于 2017-05-18T11:08:12.940 回答