Search code examples
delphipropertiesnumbersdefault

Negative property default does not seem to work


When I install the component, I look in the object inspector and the value for StoppingCount is 0! I need the value to be -1. In my code, anything above -1 will stop the for loop process at that number.

Does default not work for negative numbers?

unit myUnit;

interface

uses
  System.SysUtils, System.Classes;

type
  TmyComponent = class(TComponent)
  private
    { Private declarations }
    FStoppingCount: integer;

  protected
    { Protected declarations }
    procedure ProcessIT();

  public
    { Public declarations }

  published
    { Published declarations }

    property StoppingCount: integer read FStoppingCount write FStoppingCount default -1;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('myComponent', [TmyComponent]);
end;

procedure TmyComponent.ProcessIT();
begin
  for I := 0 to 1000 do
  begin
    DoSomething();
    if FStoppingCount = I then break;
  end;
end;

Solution

  • Negative values work just fine. The problem is that you did not actually initialize FStoppingCount to -1, so it instead gets initialized to 0 when new instances of the component are created and have their memory initially zeroed out.

    Simply declaring a non-zero default value on the property declaration is not enough. The default value is merely stored in the property's RTTI, and is used only for comparison purposes when the component is written to a DFM, and when displaying the property value in the Object Inspector. The default directive does not actually affect instances of the component in memory. You have to explicitly set the value of FStoppingCount to match the default value. This is clearly stated in the documentation:

    Properties (Delphi)

    Note: Property values are not automatically initialized to the default value. That is, the default directive controls only when property values are saved to the form file, but not the initial value of the property on a newly created instance.

    To fix your component, you need to add a constructor that initializes FStoppingCount to -1, eg:

    unit myUnit;
    
    interface
    
    uses
      System.SysUtils, System.Classes;
    
    type
      TmyComponent = class(TComponent)
      private
        { Private declarations }
        FStoppingCount: integer;
      protected
        { Protected declarations }
        procedure ProcessIT();
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override; // <-- ADD THIS!
      published
        { Published declarations }
        property StoppingCount: integer read FStoppingCount write FStoppingCount default -1;
      end;
    
    procedure Register;
    
    implementation
    
    procedure Register;
    begin
      RegisterComponents('myComponent', [TmyComponent]);
    end;
    
    constructor TmyComponent.Create(AOwner: TComponent);
    begin
      inherited;
      FStoppingCount := -1; // <-- ADD THIS!
    end;
    
    procedure TmyComponent.ProcessIT();
    begin
      for I := 0 to 1000 do
      begin
        DoSomething();
        if FStoppingCount = I then break;
      end;
    end;