Už od verze 2007 Delphi podporuje procházení přes for - in, bohužel některé třídy stále tuto podporu nemají.
Požadovaný stav:
var
bmk: TBookmark;
begin
for bmk in DBGrid1.SelectedRows do
begin
//xxx
end;
end;
Bohužel ale
[dcc32 Error] Unit18.pas(33): E2431 for-in statement cannot operate on collection type 'TBookmarkList' because 'TBookmarkList' does not contain a member for 'GetEnumerator', or it is inaccessible
Ukáži jak jednoduše doimplementovat podporu bez zásahu do zdrojových kódu RTL. Pro tuto akci využijeme class helper.
Nebudeme chodit kolem horké kaše a ukažme si kód.
unit uBookmarks;
interface
uses
db, Vcl.DBGrids;
type
// vlastni enumerator
TBookmarkListEnumerator = record
private
FIndex: Integer;
FList : TBookmarkList;
public
constructor Create(list: TBookmarkList);
function GetCurrent: TBookmark; inline;
function MoveNext: Boolean; inline;
property Current: TBookmark read GetCurrent;
end;
// class helper přidávající volání GetEnumerator
TBookmarkListHelper = class helper for TBookMarkList
public
function GetEnumerator: TBookmarkListEnumerator;
end;
implementation
{ TBookmarkListEnumerator }
constructor TBookmarkListEnumerator.Create(list: TBookmarkList);
begin
FList := list;
FIndex := 0;
end;
function TBookmarkListEnumerator.GetCurrent: TBookmark;
begin
Result := FList.Items[FIndex - 1];
end;
function TBookmarkListEnumerator.MoveNext: Boolean;
begin
Result := FIndex < FList.Count ;
if Result then
Inc(FIndex);
end;
{ TBookmarkListHelper }
function TBookmarkListHelper.GetEnumerator: TBookmarkListEnumerator;
begin
Result := TBookmarkListEnumerator.Create(Self);
end;
end.
V podstatě je to jednoduché, přes class helper přidáme funkci GetEnumerator, která vrátí vlastní enumerátor (jedná se o rekord, takže neřešíme uvolnění) a zbytek necháme na kompilátoru.
A nyní kdykoliv máme v uses jednotku s naším vylepšením můžeme použít for-in i pro TBookmarkList.
Datum: 2019-03-26 21:14:00 Tagy: db