More about enumerators: https://www.thedelphigeek.com/2007/03/fun-with-enumerators.html
unit DataSet.Enumerator;
interface
uses DB;
{
Example:
var
t: TDataSet;
begin
for t in memTable1 do
ShowMessage(t.FieldByName('Name').AsString + ' ' + t.FieldByName('Email').AsString);
end;
}
type
TDataSetEnumerator = class
private
FDataSet: TDataSet;
FDoFirst: boolean;
public
constructor Create(ADataSet: TDataSet);
function GetCurrent: TDataSet;
function MoveNext: boolean;
property Current: TDataSet read GetCurrent;
end;
TDataSetHelper = class helper for TDataSet
public
function GetEnumerator: TDataSetEnumerator;
end;
implementation
{ TDataSetEnumerator }
constructor TDataSetEnumerator.Create(ADataSet: TDataSet);
begin
FDoFirst := True;
FDataSet := ADataSet;
FDataSet.Open;
end;
function TDataSetEnumerator.GetCurrent: TDataSet;
begin
Result := FDataSet;
end;
function TDataSetEnumerator.MoveNext: boolean;
begin
if FDoFirst then
begin
FDoFirst := False;
FDataSet.First;
end else
FDataSet.Next;
Result := not FDataSet.EOF;
end;
{ TDataSetHelper }
function TDataSetHelper.GetEnumerator: TDataSetEnumerator;
begin
Result:= TDataSetEnumerator.Create(Self);
end;
end.
Example:
unit uMain;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Param, FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf,
FireDAC.DApt.Intf, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client, DataSet.Enumerator;
type
TForm1 = class(TForm)
memTable1: TFDMemTable;
fieldName: TStringField;
fieldEmail: TStringField;
procedure FormCreate(Sender: TObject);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
t: TDataSet;
begin
memTable1.Open;
memTable1.Append;
memTable1.FieldByName('Name').AsString := 'Test';
memTable1.FieldByName('Email').AsString := 'test@test.com';
memTable1.Post;
memTable1.Append;
memTable1.FieldByName('Name').AsString := 'Test 2';
memTable1.FieldByName('Email').AsString := 'test 2@test.com';
memTable1.Post;
memTable1.Append;
memTable1.FieldByName('Name').AsString := 'Test 3';
memTable1.FieldByName('Email').AsString := 'test 3@test.com';
memTable1.Post;
for t in memTable1 do
ShowMessage(t.FieldByName('Name').AsString + ' ' + t.FieldByName('Email').AsString);
end;
end.
uses
System.Generics.Collections;
function Count<T>(AList: TEnumerable<T>): Integer;
var
Enumerator: TEnumerator<T>;
begin
Result := 0;
Enumerator := AList.GetEnumerator;
try
while Enumerator.MoveNext do
Inc(Result);
finally
Enumerator.Free;
end;
end;
function First<T>(AList: TEnumerable<T>): T;
var
Enumerator: TEnumerator<T>;
begin
Enumerator := AList.GetEnumerator;
try
if Enumerator.MoveNext then
Exit(Enumerator.Current)
else
raise Exception.Create('First<T>: Sequence contains no elements');
finally
Enumerator.Free;
end;
end;
function Any<T>(AList: TEnumerable<T>): Boolean;
var
Enumerator: TEnumerator<T>;
begin
Enumerator := AList.GetEnumerator;
try
Result := Enumerator.MoveNext;
finally
Enumerator.Free;
end;
end;
function ToArray<T>(AList: TEnumerable<T>): TArray<T>;
var
List: TList<T>;
begin
List := TList<T>.Create;
try
List.AddRange(AList);
Result := List.ToArray;
finally
List.Free;
end;
end;
uses
System.SysUtils, System.Generics.Collections, System.Generics.Defaults;
type
TEnumerableHelper<T> = record helper for TEnumerable<T>
function Any: Boolean;
function First: T;
function ToArray: TArray<T>;
function Count: Integer;
end;
{ Implementatie }
function TEnumerableHelper<T>.Any: Boolean;
var
Enumerator: TEnumerator<T>;
begin
Enumerator := Self.GetEnumerator;
try
Result := Enumerator.MoveNext;
finally
Enumerator.Free;
end;
end;
function TEnumerableHelper<T>.First: T;
var
Enumerator: TEnumerator<T>;
begin
Enumerator := Self.GetEnumerator;
try
if Enumerator.MoveNext then
Exit(Enumerator.Current)
else
raise Exception.Create('First<T>: Sequence contains no elements');
finally
Enumerator.Free;
end;
end;
function TEnumerableHelper<T>.ToArray: TArray<T>;
var
TempList: TList<T>;
begin
TempList := TList<T>.Create;
try
TempList.AddRange(Self);
Result := TempList.ToArray;
finally
TempList.Free;
end;
end;
function TEnumerableHelper<T>.Count: Integer;
var
Enumerator: TEnumerator<T>;
begin
Result := 0;
Enumerator := Self.GetEnumerator;
try
while Enumerator.MoveNext do
Inc(Result);
finally
Enumerator.Free;
end;
end;
Usage
var
List: TList<Integer>;
FirstItem: Integer;
Items: TArray<Integer>;
begin
List := TList<Integer>.Create;
try
List.AddRange([5, 10, 15]);
if List.Any then
FirstItem := List.First;
Items := List.ToArray;
finally
List.Free;
end;
end;
416300cookie-checkDelphi enumerate over TDataSet