我正在尝试以下代码来创建不区分大小写的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。一个单独的“EqualityComparer”用于IndexOf,所以问题变成了如何改变它?
Update2:我只想添加Johan的答案,然后可以像这样创建列表:
MyCIList := TCaseInsensitiveList<string>.Create(
TStringComparer.OrdinalIgnoreCase(),
TStringComparer.OrdinalIgnoreCase());
答案 0 :(得分: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
虚拟成本是有代价的,这就是我选择保护基础类变量的原因。
答案 1 :(得分:1)
此问题已在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;