tags:

views:

1557

answers:

5

I have an integer field in a ClientDataSet and I need to compare to some values, something like this:

I can use const

const
  mvValue1 = 1;
  mvValue2 = 2;

if ClientDataSet_Field.AsInteger = mvValue1 then

or enums

TMyValues = (mvValue1 = 1, mvValue2 = 2);

if ClientDataSet_Field.AsInteger = Integer(mvValue1) then

or class const

TMyValue = class
const
   Value1 = 1;
   Value2 = 2;
end;

if ClientDataSet_Field.AsInteger = TMyValues.Value1 then

I like the class const approach but it seems that is not the delphi way, So I want to know what do you think

A: 

so many options! :-) i prefer enums and routinely use them as you describe. one of the parts i like is that i can use them with a "for" loop. i do use class constants as well but prefer enums (even private enums) depending on what i'm trying to achieve.

TMyType=class
private const    // d2007 & later i think
  iMaxItems=1;   // d2007 & later i think
private type     // d2007 & later i think
  TMyValues = (mvValue1 = 1, mvValue2 = 2);     // d2007 & later i think
private
public
end;
X-Ray
Class-specific consts and types were introduce in Delphi 2005, possibly even Delphi 8. (Just because so many people skipped directly from Delphi 7 to Delphi 2007 doesn't mean the intervening versions didn't have any new features.)
Rob Kennedy
+4  A: 

I wouldn't say that class consts are not the Delphi way. It's just they have been introduced to Delphi quite recently, and a lot of books and articles you'll find on the internet were written before their introduction, and thus you won't see them widely used. Many Delphi developers (I'd say the majority) will have started using Delphi before they were made available, and thus they're not the first thing that one thinks about.

Steve
You are right, I Just notice that DBX4 use class cons in TDBXCommandTypes
Marioh
+3  A: 

Declaration:

type
  TMyValues = class
    type TMyEnum = (myValue1, myValue2, myValue3, myValue4);
    const MyStrVals: array [TMyEnum] of string =
      ('One', 'Two', 'Three', 'Four');
    const MyIntVals: array [TMyEnum] of integer =
      (1, 2, 3, 4);
  end;

Usage:

if ClientDataSet_Field.AsInteger = TMyValues.MyIntVals[myValue1] then

A cast would generally be my last choice.

Jim McKeeth
when using the class const approach you don´t need to cast. Thanks for the feedback
Marioh
+3  A: 

One thing to consider is backwards compatibility - class constants are relatively new to Delphi so if your code has to be sharable with previous versions than they are out.

I typically use enumerated types, with the difference from yours is that my first enumeration is usually an 'undefined' item to represent NULL or 0 in an int field.

TmyValues = (myvUndefined, myvDescription1, myvDescription2)

if ClientDataSet_Field.AsInteger = Ord(myvDescription1) then...

To use a little bit of Jim McKeeth's answer - if you need to display to the user a text viewable version, or if you need to convert their selected text into the enumerated type, then an array comes in handy in conjuction with the type:

const MYVALS: array [TmyValues ] of string = ('', 'Description1', 'Description2');

You can then have utility functions to set/get the enumerated type to/from a string:

Function MyValString(const pMyVal:TmyValues):string;
begin
  result := MYVALS[Ord(pMyVal)];
end;

Function StringToMyVal(const pMyVal:String):TMyValues;
var i:Integer;
begin
  result := myvUndefined;
  for i := Low(MYVALS) to High(MYVALS) do
  begin
    if SameText(pMyVal, MYVALS[i]) then
    begin
      result := TMyValues(i);
      break;
    end;
  end;
end;

Continuing on... you can have scatter routine to set a combo/list box:

Procedure SetList(const DestList:TStrings);
begin
  DestList.Clear;
  for i := Low(MYVALS) to High(MYVALS) do
  begin
    DestList.Insert(MYVALS[i]);
  end;
end;

In code: SetList(Combo1.Items) or SetList(ListBox1.Items)..

Then if you are seeing the pattern here... useful utility functions surrounding your enumeration, then you add everything to it's own class and put this class into it's own unit named MyValueEnumeration or whaterver. You end up with all the code surrounding this enumeration in one place and keep adding the utility functions as you need them. If you keep the unit clean - don't mix in other unrelated functionality then it will stay very handy for all projects related to that enumeration.

You'll see more patterns as time goes and you use the same functionality over and over again and you'll build a better mousetrap again.

Darian Miller
There's actually an RTTI trick to get the name of an enum value as a string. Take a look at the GetEnumName function in the TypInfo unit.
Mason Wheeler
A: 

An option you haven't thought of is to use a lookup table in the database and then you can check against the string in the database.

eg.

 Select value, Description from tbl_values inner join tbl_lookup_values where tbl_values.Value = tbl_lookup_values.value

if ClientDataSet_Field.AsString = 'ValueIwant' then
Toby Allen
in this example I need to compare the value with a (integer) constant value to do some stuff not to display the description. the description of the constant value it's in a lookup table.
Marioh