Search code examples
delphidelphi-7

Delphi: How can I reset all class fields to zero value?


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)


Solution

  • 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.