I have a class with many numeric fields, number of fields will grow up with project development, so would be nice to have a way to reset all fields, no matter how many will be added in future.
TParams = class
public
defined: boolean;
FirstValue: byte; // reset from here
A0: single;
A1: single;
H1: TPoint;
// ...............
A100: single;
LastValue: byte; // to here
procedure Reset;
end;
The only idea comes to mind is to insert 2 fields: before and after block that should be reseted, and use FillMemory:
procedure TParams.Reset;
begin
FillMemory(@FirstValue, Integer(@LastValue)-Integer(@FirstValue),0);
end;
Is there better way ? (Im using Delphi 7)
David Heffernan already said it: what you are doing is an ugly hack, and not very clean. He also gave the hint: Turn your numeric fields into a record:
type
TParams = class
public
Defined: Boolean;
Numbers: record
A0: Single;
A1: Single;
H1: TPoint;
A100: Single;
end;
procedure Reset;
end;
Now it is very simple, you can Reset
by doing the following:
procedure TParams.Reset;
begin
FillChar(Numbers, SizeOf(Numbers), 0);
end;
A simple test:
procedure Test;
var
P: TParams;
begin
P := TParams.Create;
try
Writeln(Format('%f %f (%d, %d) %f', [P.Numbers.A0, P.Numbers.A1, P.Numbers.H1.X, P.Numbers.H1.Y, P.Numbers.A100]));
P.Numbers.A0 := 1.0;
P.Numbers.A1 := 2.0;
P.Numbers.H1 := Point(11, 22);
P.Numbers.A100 := 77.0;
Writeln(Format('%f %f (%d, %d) %f', [P.Numbers.A0, P.Numbers.A1, P.Numbers.H1.X, P.Numbers.H1.Y, P.Numbers.A100]));
P.Reset;
Writeln(Format('%f %f (%d, %d) %f', [P.Numbers.A0, P.Numbers.A1, P.Numbers.H1.X, P.Numbers.H1.Y, P.Numbers.A100]));
finally
P.Free;
end;
end;
This produces the following output:
0.00 0.00 (0, 0) 0.00
1.00 2.00 (11, 22) 77.00
0.00 0.00 (0, 0) 0.00
Alternatively, you can do the following:
TNumbers = record
A0: Single;
A1: Single;
H1: TPoint;
A100: Single;
end;
TParams = class
public
Defined: Boolean;
Numbers: TNumbers;
procedure Reset;
end;
For those with a version with generics (I know you are using Delphi 7, which has no generics, but anyway, for others), that will simplify Reset
a little:
procedure TParams.Reset;
begin
Numbers := Default(TNumbers);
end;
Default
has the advantage that it will properly finalize and initialize the record, just in case it has managed types (strings, interfaces, etc.) in it.