Delphi's Case <X> of statement works with everything that is Ordinal. integer, char, enumerations, it even works with boolean.
However, it does not work with strings. And I've come across some places where it would be very handy to have a Case <String> of.
Luckily, with Delphi 2010 came anonymous methods and with the combination of a Dictionary we can finally have something that works as a Case <String> of.
TStringCase is the type, that will be used the most, but with the generic TCase, (almost) everything can be used for a Case statement.
The implementation is very simple:
And this is how it's used:
The usage has some overhead compared to the standard case, but I think it is still prettier than a bunch of if-then-else's.
Download is available here.
case b of true : MakeSomething; false : DoNotMakeSomething; end;
However, it does not work with strings. And I've come across some places where it would be very handy to have a Case <String> of.
Luckily, with Delphi 2010 came anonymous methods and with the combination of a Dictionary we can finally have something that works as a Case <String> of.
type
TProc = reference to procedure;
TCase<T> = class
private
fDict : TDictionary<T,TProc>;
fElse: TProc;
public
constructor Create;
destructor Destroy; override;
procedure addEntry(aKey : T; aProc :TProc);
procedure addEntries(const aKeys : array of T; aProc : TProc);
procedure switch(aKey : T);
property ElseCase : TProc read fElse write fElse;
end;
TStringCase = TCase<string>;
TStringCase is the type, that will be used the most, but with the generic TCase, (almost) everything can be used for a Case statement.
The implementation is very simple:
procedure TCase<T>.addEntries(const aKeys: array of T; aProc: TProc);
var
key : T;
begin
for key in aKeys do
addEntry(key,aProc);
end;
procedure TCase<T>.addEntry(aKey: T; aProc: TProc);
begin
fDict.Add(aKey, aProc);
end;
constructor TCase<T>.Create;
begin
fDict := TDictionary<T,TProc>.Create;
end;
destructor TCase<T>.Destroy;
begin
fDict.Free;
inherited;
end;
procedure TCase<T>.switch(aKey: T);
var
p : TProc;
begin
if fDict.TryGetValue(aKey, p) then
p()
else
if assigned(fElse) then fElse();
end;And this is how it's used:
procedure UseStringCase;
var
sc : TStringCase;
begin
sc :=TStringCase.Create;
try
// setup the case
sc.addEntry('STRING1',procedure
begin
Label1.Caption := 'First Option';
end);
sc.addEntry('STRING1',procedure
begin
Label1.Caption := 'Second Option';
end);
sc.addEntries(['STRING3','STRING4','STRING5'],procedure
begin
Label1.Caption := 'one of three options';
end);
sc.ElseProc := procedure
begin
Label1.Caption := 'Something else';
end;
sc.switch(Edit1.Text); // execute the right procedure
finally
sc.Free;
end;
end;The usage has some overhead compared to the standard case, but I think it is still prettier than a bunch of if-then-else's.
procedure UseIfThenElse;
var
s : string;
begin
s := Edit1.Text;
if s = 'STRING1' then
begin
Label1.Caption := 'First Option';
end
else if s = 'STRING2' then
begin
Label1.Caption := 'Second Option';
end
else if (s = 'STRING3') or (s = 'STRING4') or (s = 'STRING5') then
begin
Label1.Caption := 'one of three options';
end
else
begin
Label1.Caption := 'Something else';
end;
end;Download is available here.
Keine Kommentare:
Kommentar veröffentlichen