Enumerated Type, Subrange Type and Set Type in Delphi
Enumerated Types
An enumerated type defines an ordered set of values by simply listing identifiers that represent the values. This helps to make codes to readable and reliable. Enum variable can store any one value from the list. To declare an enumerated type, we use the syntax:
type typeName = (val1, val2, val3, val4, ...,valn);
Where typeName and each val are valid identifiers.
For example, the declaration:
type TFileType = (ftPDF, ftDoc, ftXLSX, ftHTML, ftRTF, ftTxt);
defines an enumerated type called TFileType, whose identifiers are ftPDF, ftDoc, ftXLSX, ftHTML, ftRTF and ftTxt. Values of identifiers would be 0, 1, 2, 3, 4 and 5 where Ord(ftPDF) returns 0, Ord(ftDoc) returns 1, and so on.
When you declare an enumerated type, you are declaring each val to be a constant. So we should be careful that If the identifiers are used for another purpose within the same scope then naming conflicts may occur.
For example, suppose you declare the type:
type TSound = (Click, Dot, Beep);
Unfortunately, Click is also the name of a method defined for TControl and all of the objects in VCL that descend from it. So if you are writing an application and you create an event handler like:
procedure TForm1.EditEnter(Sender: TObject);
var
vow: TSound;
begin
...
vow:= Click;
end;
you will get a compilation error; the compiler interprets Click within the scope of the procedure as a reference to a Click method of a TForm. You can work around this by qualifying the identifier; thus, if TSound is declared in MyUnit, you would use:
vow:= MyUnit.Click;
A better solution, however, is to choose constant names that are not likely to conflict with other identifiers. So during declaration of enumeration always use prefix which will represent the enum type.
Examples:
type
TSound = (tsClick, tsClack, tsClock);
TMyColor = (mcRed, mcBlue, mcGreen, mcYellow, mcOrange);
Enumerated Types Values
By default the enumerated values start from 0 and follow the sequence in which their identifiers are listed in the type declaration. We can override this by explicitly assigning to some other values in the declaration. To assign value, follow its identifier with = constant expression, where constant expression is a constant expression that evaluates to an integer.
For example:
type Size = (szSmall = 5, szMedium = 10, szLarge = Small + Medium);
defined a type called Size whose possible values include szSmall, szMedium, and szLarge, where Ord(Small) returns 5, Ord(Medium)returns 10, and Ord(Large) returns 15.
Enumerated Property
When we write our own custom components, sometime we need to add enum typed properties for better understand and accessibility. We can declare a enum property type like as follow.
For example, if you declare the enumerated type:
type
TFileType = (ftPDF, ftDoc, ftXLSX, ftHTML, ftRTF, ftTxt);
First declaring private variable to store and access property value.
Private
FfileType: TfileType;
Now declaring enum property as publish so that it will display on property editor.
publish
Property FileType: TfileType read FfileType write Ffiletype;
Example
Delphi VCL Library uses enumerated types in many places. For example, the style of the border of a form is defined as follows:
type
TFormBorderStyle = (bsNone, bsSingle, bsSizeable, bsDialog, bsSizeToolWin, bsToolWindow);
When the value of a property is an enumeration, you usually can choose from the list of values displayed in the Object Inspector, as shown in below image.
Subrange Types
A Subrange type represents a subset of the values of a particular type. We can declare a Subrange type in the form of Low..High, where Low and High are constant expressions of the same ordinal type. It defines that a Variable of subrange type can only have values between Low and High. If values of a variable is outside a given boundary then compiler error will show. Subrange types can be defined of type character, integer, Ordinal type like Enum.
We can declare a Subrange type by following way
type typeName = (val1..valn);
For example, if you declare the enumerated type:
type
TFileType = (ftPDF, ftDoc, ftXLSX, ftHTML, ftRTF, ftTxt);
Here TFileType includes the values ftPDF, ftDoc, ftXLSX, ftHTML, ftRTF, ftTxt.
you can then define a subrange type like:
type
TFileTypeRange = ftPDF.. ftXLSX;
Here TFileTypeRange includes the values ftPDF, ftDoc, ftXLSX.
You can use numeric constants and characters (string constants of length 1) to define subrange types:
type
SomeNumbers = -128..127;
Caps = 'A'..'Z';
Smalls = ‘a’..’z’;
When you use numeric or character constants to define a subrange, the base type is the smallest integer or character type that contains the specified range.
The LowerBound..UpperBound construction itself functions as a type name, so you can use it directly in variable declarations. For example:
var SomeNum: 1..500;
declares an integer variable whose value can be anywhere in the range from 1 through 500.
A better example of subrange type. Here I am allowing only letters to type into Edit box.
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not (key in ['a'..'z', 'A'..'Z']) then
key := #0;
end;
we write above example as following also with declaring subrange type and variables.
type
TSmalls = 'a'..'z';
TCaps = 'A'..'Z';
.....
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
v1: TSmalls;
v2: TCaps;
begin
if not (key in [v1, v2]) then
key := #0;
end;
Subrange Property
Declaring a subrange property so that it will not allow a value beyond the range. For example, if you declare the range type as:
type
TEntryAge = (20..30);
So here I declare a subrange which accept value from 20 to 30.
First declaring private variable to store and access property value.
Private
FEntryAge: TEntryAge;
Now declaring subrange property as publish so that it will display on property editor.
Publish
Property EntryAge: TEntryAge read FEntryAge write FEntryAge;
So here for Property EntryAge we can assign values between 20 to 30 only.
Set Types
Set type is a collection of values of the same ordinal type. Where as enumerations allow a variable to have only one value from a fixed number of values, sets allow you to have many combination of the given values like none, 1, some, or all. A set is defined using the set of keyword. Set types are usually defined with subranges. A limitation on sets is that they can hold up to 255 elements.
type typeName = set of (val1..valn);
type typeName = set of TEnumarationType;
To assign a value to a set type variable, use the square brackets and list all the elements of the set. As in:
Note 1: every set type variable can hold the empty set, denoted by [].
Note 2: the order of the elements in a set has no meaning, nor is it meaningful for an element (value) to be included twice in a set.
type
TDigits = set of '1'..'9'; // Set of numeric digit characters
var
digits : TDigits; // Set variable
myChar : char;
begin
// At the start, digits has all set values switched off
// So let us switch some on. Notice how we can switch on single
// values, and ranges, all in the one assignment:
digits := ['2', '4'..'7'];
// Now we can test to see what we have set on:
for myChar := '1' to '9' do
if myChar In digits then
ShowMessageFmt('''%s'' is in digits',[myChar])
else
ShowMessageFmt('''%s'' is not in digits',[myChar])
end;
Including and excluding Set Type Values
Delphi provides a couple of routines that allow you to include (value) or exclude (value) individual values into a Set without affecting other values:
type
// We define a set by type - bytes have the range : 0 to 255
TNums = set of Byte;
var
nums : TNums;
begin
nums := [20..50]; // range of values between 20 to 50
Include(nums, 12); // Added an additional value : 12
Exclude(nums, 35); // removed a value : 35
end;
Set operators
Just as with numbers, sets have primitive operators:
+ The union of two sets
* The intersection of two sets
- The difference of two sets
= Tests for identical sets
<> Tests for non-identical sets
>= Is one set a subset of another
<= Is one set a super set of another
These operators give great flexibility in set handling:
type
TNums = set of 1..9;
var
nums1, nums2, nums3, nums4, nums5, nums6 : TNums;
begin
nums1 := [1,2,3];
nums2 := [1,2,4];
nums3 := [1,2,3,4,5,6,7,8,9];
nums4 := nums1 + nums2; // nums4 now [1,2,3,4]
nums5 := nums1 * nums2; // nums5 now [1,2]
nums6 := nums1 - nums2; // nums6 now [3]
// Test for equality
if nums1 = nums2 then
ShowMessage('nums1 = nums2')
else
ShowMessage('nums1 <> nums2');
// Test for inequality
if nums1 <> nums3 then
ShowMessage('nums1 <> nums3')
else
ShowMessage('nums1 = nums3');
// Is nums1 a subset of nums3?
if nums1 <= nums3 then
ShowMessage('nums1 is a subset of nums3')
else
ShowMessage('nums1 is not a subset of nums3');
// Is nums1 a superset of nums3?
if nums1 >= nums3 then
ShowMessage('nums1 is a superset of nums3')
else
ShowMessage('nums1 is not a superset of nums3');
end;
IN Keyword
To test if an element is included in the set (variable) use the IN keyword:
For Example allow only number into edit box.
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if not (key IN ['0'..'9']) then
key := #0;
end;
Sets used in MessageDlg function
A MessageDlg function is used to bring up a message box and obtain the user's response. One of the parameters of the function is the Buttons parameter of type TMsgDlgButtons.
TMsgDlgButtons is defined as a set of (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp).
MessageDlg(‘Test Message’, mtInformation, [mbOk,mbcancel]);
Set Property
In Delphi form property we can see a set example with property Bordericons. A Delphi form can have none of these icons, one of them, or more than one on form Title. When working with the Object Inspector, you can provide the values of a set by expanding the selection and toggling on and off the presence of each value.
type
TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp);
TBorderIcons = set of TBorderIcon;
Another property based on a set type is the style of a font of a form. Possible values indicate a bold, italic, underline, and strikethrough font. Of course the same font can be both italic and bold, have no attributes, or have them all. For this reason it is declared as a set. You can assign values to this set in the code of a program as follows:
Font.Style := []; // no style
Font.Style := [fsBold]; // bold style only
Font.Style := [fsBold, fsItalic]; // two styles
You can also operate on a set in many different ways, including adding two variables of the same set type (or, to be more precise, computing the union of the two set variables):
Font.Style := OldStyle + [fsUnderline]; // two sets
Got detailed information about enumerated type.
ReplyDeleteAzure Training in Chennai | Devops Training in Chennai | AWS Training in Chennai
Amazing! This blog looks exactly like my old one! It's on a completely different subject but it has pretty much the same layout and design. Great choice of colors! mac neukölln berlin
ReplyDelete