Home Contents Search

CASE & Classes
Error Message Issue #23 skins QTime Perpetual Newbie Perpetual Newbie Perpetual Newbie Perpetual Newbie How Convert User Registration rabbit hole CASE & Classes skins Premium 5 Premium 6 Premium Domains Premium 2 Premium 3 Premium 4 Rare domains cities_realestate Similar   Websites education_sites entertainment_sites games misc_sites LLLL.com Site Acronym 2 Acronym 4 Acronym 5 Acronym 6 Acronym 7 Acronym 8 Acronym 9 Acronym 10 Acronym 3 Brandable sites Pin Yin sites service_sites technology Acronym sites Payment Options About Our Office

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

Copyright © 2007 undu.com                    Powered by Engineer Partner The One Stop Outsource