Programming With Style - Using CASE With Strings & Classes
by SZ - iammyself@usa.net
1. Introduction
Do you ever wonder why you can't use stings with CASE statement in Delphi?
Same question here.
The fact is - it doesn't mean we can't use CASE at all! Many of pros think so
and in result they ended up with compacted IF..THEN..ELSE . IF..THEN..ELSE.
like this one ...
if sString ='First' then
begin
<Do something>
end// if sString ='First' then
else
begin
if sString ='Second' then
begin
<Do something>
end// if sString ='Second' then
end;//else if sString ='First' then
I always had a bad feeling about structure like this and last year I finally
found what this construction could produce potential bug.
Try to find it in this peace of code or see (*) at the end.
if sString ='First' then
begin
<Do something>
end// if sString ='First' then
else
if sString ='Second' then if X=5 then Y:=10
else
if sString ='Third' then
begin
<Do something>
end;// if sString ='Third' then
2. CASE with strings
Here is a technique how to use CASE with strings. To use CASE we need to
enumerate our stings somehow. One way to do it - put all strings into array (see
SZStringsArray below). By putting those stings into array we're enumerating it -
'First' will be 1st element of array, 'Second' - 2nd element, 'Third' -3rd
element. So now we can perform CASE statement not on string but on array indexes
instead.
Const
nStringsCount = 3;
SZStringsArray : array[1..nStringsCount] of strings = ('First',
'Second','Third');
Now then we have array we can finally use CASE
Var
INdx : integer;
Begin
for iNdx:=1 to nStringsCount do
begin
if sPassedString = SZStringsArray[iNdx] then
begin
//here is our CASE
CASE iNdx of
1 ://First
begin
<do something>
end;//1
2 : //Second
begin
<do something>
end;//2
3:
begin
<do something>
end;//3
else
begin
<not in list>
end;//else
end;//CASE iNdx
break;//exit from loop
end;//if sPassedString = SZStringsArray[iNdx] then
end;// for iNdx:=1 to nStringsCount do
End.
of course if for example all string have distinct first character you can use
quick-n-dirty technique
CASE UpperCase(sPassedString[1]) of
'F' ://First
begin
<do something>
end;//F
'S' : //Second
begin
<do something>
end;//S
'T'://third
begin
<do something>
end;//T
end;//CASE UpperCase(sPassedString[1])
3. CASE with classes(classes should have the same parent)
Same technique works with classes
So instead of code like this
if Sender is TEdit then <Do something>
Else
If Sender is TMemo then <Do something>
we can use CASE statement like this one by enumerating classes using array (see
SZClassesArray below)
type
TSZComponentsClass = class of TComponent;
Const
nClassesCount =2;
SZClassesArray : array[1.. nClassesCount] of TSZComponentsClass =
(TEdit, TMemo, TComboBox);
Var
INdx : integer;
Begin
for iNdx:=1 to nStringsCount do
begin
if Sender is SZClassesArray[iNdx] then
begin
//here is out CASE
CASE iNdx of
1 ://TEdit
begin
Tedit(Sender).Text:=...
<do something>
end;//1
2 : //TMemo
begin
Tmemo(Sender).text:=
end;//2
3:
begin
TComboBox(Sender).ItemIndex:=5;
end;//3
else
begin
<other class>
end;//else
end;//CASE iNdx
break;
end;//if sPassedString = SZStringsArray[iNdx] then
end;// for iNdx:=1 to nStringsCount do
end.
You can use same technique if your strings are in TStrings structure inside
visual Delphi component like TlistBox, Tcombobox, Tmemo, TPageControl etc. with
one precaution - almost all of them have some Sort functionality so by sorting
it you can break your original enumeration. Also by adding new sting you need to
re-enumerate your CASE choices.
Engoy!
- SZ -
(*) bug...
If X =5 program will never go to line "if sString ='Third'" because ELSE is
actually for "if X=5" statement not for "if sString ='Second'" as it seems
if sString ='Second' then if X=5 then Y:=10
else
if sString ='Third' then
The solution would be to put another ELSE or use BEGIN..END (which I prefer
most.)
1st solution
if sString ='Second' then if X=5 then Y:=10 ELSE
else
if sString ='Third' then
2nd solution (prefered)
if sString ='First' then
begin
<Do something>
end// if sString ='First' then
else
if sString ='Second' then
begin
if X=5 then
begin
Y:=10
end;
end
else
begin
if sString ='Third' then
begin
<Do something>
end;// if sString ='Third' then
end