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