Reputation: 9
Given the declarations :
Unit MyUnit;
interface
type
TMyFileStream= class(TFileStream);
...
end;
var
a1,a2,a3,a4,a5: integer;
b1,b2,b3: boolean;
c1: char;
d1,d2,d3,d4: TDateTime;
f1,f2,f3,f4,f5,f6,f7,f8: TMyFileStream // LineX
...
procedure MyProc;
implementation
procedure MyProc
begin
// I wanna iterate over all integer (or any other type) variables here with a loop regardless of their count and identifier name
end;
Some specific type variables' count regularly changes in code - mostly increases as I add new functions. How can I reference them in a loop to take the same action on all of them ? I want to preserve the fact that when I add a new one, the code needs to be modified at only one place.
I've already thought of putting them in an (either static or dynamic) array, but this involves the modifocation of code at every location where they are referenced, which is much-much-much work that I wanna spare if it's possible by any means.
There's currently 38 variables I want to take an acton upon, the references' count is a multiple of it far above 100.
Hope I was clear enough. Thanks for any idea.
Peter
Upvotes: 0
Views: 857
Reputation: 14832
I've already thought of putting them in an (either static or dynamic) array, but this involves the modifocation of code at every location where they are referenced, which is much-much-much work that I wanna spare if it's possible by any means.
So what! Do it!
The longer you put off fixing horrible code, the worse it will get. Also, it's not nearly as bad as you think.
E.g. Change the following:
var
a1,a2,a3,a4,a5: integer;
to:
var
A: array[1..5] of Integer;
Now everything that was referring to a?
will fail to compile (unless you had scope conflicts, which would be a simmering pot of disaster in any case). These compilation errors can easily be fixed by changing a?
to a[?]
.
If you simply go through a cycle of: compile --> fix --> compile --> fix --> ...
You'll find you can clean up a lot faster than you think.
Upvotes: 0
Reputation: 47704
Although the design smells, this is what pointers are made for:
type
PMyFileStream = ^TMyFileStream;
TMyFileStream= class(TFileStream)
end;
var
a1,a2,a3,a4,a5: integer;
b1,b2,b3: boolean;
c1: char;
d1,d2,d3,d4: TDateTime;
f1,f2,f3,f4,f5,f6,f7,f8: TMyFileStream; // LineX
function GetVarsInt: TArray<PInteger>;
begin
result := TArray<PInteger>.Create(@a1, @a2, @a3, @a4, @a5);
end;
function GetVarsBool: TArray<PBoolean>;
begin
result := TArray<PBoolean>.Create(@b1, @b2, @b3);
end;
function GetVarsChar: TArray<PChar>;
begin
result := TArray<PChar>.Create(@c1);
end;
function GetVarsDateTime: TArray<PDateTime>;
begin
result := TArray<PDateTime>.Create(@d1, @d2, @d3, @d4);
end;
function GetVarsMyFileStream: TArray<PMyFileStream>;
begin
result := TArray<PMyFileStream>.Create(@f1, @f2, @f3, @f4, @f5, @f6, @f7, @f8);
end;
procedure HandleInt(var Value: Integer);
begin
end;
procedure HandleBool(var Value: Boolean);
begin
end;
procedure HandleChar(var Value: Char);
begin
end;
procedure HandleDateTime(var Value: TDateTime);
begin
end;
procedure HandleMyFileStream(var Value: TMyFileStream);
begin
end;
procedure MyProc;
var
vInt: PInteger;
vBool: PBoolean;
vChar: PChar;
vDateTime: PDateTime;
vMyFileStream: PMyFileStream;
begin
for vInt in GetVarsInt do
HandleInt(vInt^);
for vBool in GetVarsBool do
HandleBool(vBool^);
for vChar in GetVarsChar do
HandleChar(vChar^);
for vDateTime in GetVarsDateTime do
HandleDateTime(vDateTime^);
for vMyFileStream in GetVarsMyFileStream do
HandleMyFileStream(vMyFileStream^);
end;
In case of the TMyFileStream variables, you might get away with no pointers when you only want to manipulate the existing object instances.
Upvotes: 5
Reputation: 4353
If you put these variables in a class you can use RTTI to loop over the properties of that class. There is no method that I know of to loop over variables that do not belong to a class.
Upvotes: 2