コピーされる文字列の一時コピーを保持するために余分な配列が割り当てられることを気にしないのであれば、Davidの答えは簡単です。特にリストが大きい場合、メモリ使用量を減らしたい場合は、ループの方が適しています。
var
MyList: TList<String>;
I: Integer;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
for i := 0 to MyList.Capacity-1 do
MyList.Add(MyListBox.Items[I]);
...
finally
MyList.Free;
end;
end;
または:
var
MyList: TList<String>;
S: String;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
for S in MyListBox.Items do
MyList.Add(S);
...
finally
MyList.Free;
end;
end;
ただし、手動でループしたくない場合は、カスタム列挙子を作成して、TStrings
データを直接渡しTList<String>
て文字列をコピーできるようにすることをお勧めします。
type
TStringsEnumeratorWrapper = class(TEnumerator<String>)
protected
FEnum: TStringsEnumerator;
function DoGetCurrent: String; override;
function DoMoveNext: Boolean; override;
public
constructor Create(AStrings: TStrings);
destructor Destroy; override;
end;
constructor TStringsEnumeratorWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FEnum := AStrings.GetEnumerator;
end;
destructor TStringsEnumeratorWrapper.Destroy;
begin
FEnum.Free;
inherited Destroy;
end;
function TStringsEnumeratorWrapper.DoGetCurrent: String;
begin
Result := FEnum.Current;
end;
function TStringsEnumeratorWrapper.DoMoveNext: Boolean;
begin
Result := FEnum.MoveNext;
end;
type
TStringsEnumerableWrapper = class(TEnumerable<String>)
protected
FStrings: TStrings;
function DoGetEnumerator: TEnumerator<T>; override;
public
constructor Create(AStrings: TStrings);
end;
constructor TStringsEnumerableWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FStrings := AStrings;
end;
function TStringsEnumerableWrapper.DoGetEnumerator: TEnumerator<T>;
begin
Result := TStringsEnumeratorWrapper.Create(FStrings);
end;
var
MyList: TList<String>;
Enum: TStringsEnumerableWrapper;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
Enum := TStringsEnumerableWrapper.Create(MyListBox.Items);
try
MyList.AddRange(Enum);
finally
Enum.Free;
end;
...
finally
MyList.Free;
end;
end;
または:
type
TStringsEnumeratorWrapper = class(TObject, IEnumerator<String>)
protected
FEnum: TStringsEnumerator;
public
constructor Create(AStrings: TStrings);
destructor Destroy; override;
function GetCurrent: String;
function MoveNext: Boolean;
procedure Reset;
end;
constructor TStringsEnumeratorWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FEnum := AStrings.GetEnumerator;
end;
destructor TStringsEnumeratorWrapper.Destroy;
begin
FEnum.Free;
inherited Destroy;
end;
function TStringsEnumeratorWrapper.GetCurrent: String;
begin
Result := FEnum.Current;
end;
function TStringsEnumeratorWrapper.MoveNext: Boolean;
begin
Result := FEnum.MoveNext;
end;
procedure TStringsEnumeratorWrapper.Reset;
begin
//FEnum.Reset;
end;
type
TStringsEnumerableWrapper = class(TObject, IEnumerable<String>)
protected
FStrings: TStrings;
public
constructor Create(AStrings: TStrings);
function GetEnumerator: IEnumerator<String>;
end;
constructor TStringsEnumerableWrapper.Create(AStrings: TStrings);
begin
inherited Create;
FStrings := AStrings;
end;
function TStringsEnumerableWrapper.GetEnumerator: IEnumerator<String>;
begin
Result := TStringsEnumeratorWrapper.Create(FStrings);
end;
var
MyList: TList<String>;
begin
MyList := TList<String>.Create;
try
MyList.Capacity := MyListBox.Items.Count;
MyList.AddRange(TStringsEnumerableWrapper.Create(MyListBox.Items));
...
finally
MyList.Free;
end;
end;
確かに、Davidの回答ほどエレガントではありませんが、列挙子はリスト項目のループを容易にするように設計されています(したがって、for..in
ループ構文の作成を可能にしました)。