5
votes

I've written a component who has a Variant property for which I would like to set a default value.

TMyComponent = class(TComponent)
private
  FVariantValue : Variant;
published
  property VariantValue : Variant read FVariantValue write FVariantValue default False;
end;

On compilation, I get the following error on the VariantValue property line:

E2026 Constant expression expected

Doing the same thing with a Boolean property doesn't cause any kind of error.

I read a little bit of documentation but I didn't find nothing about Variant properties default values.

3

3 Answers

9
votes

Be careful here. The default directive does not do anything to set the value of the property itself. It only affects whether or not the value is explicitly saved in the .dfm file. If you specify a default value for a property you still have to ensure that the constructor initializes the backing field to that value.

Properties : Storage Specifiers

When saving a component's state, the storage specifiers of the component's published properties are checked. If a property's current value is different from its default value (or if there is no default value) and the stored specifier is True, then the property's value is saved. Otherwise, the property's value is not saved.

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.

This is just a hint to the component streaming system that it doesn't need to store this value explicitly in the .dfm - your part of the contract is to ensure that you actually initialize the backing field to that value. The appropriate place to do this type of initialization is in the component's constructor:

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FVariantValue := False;
end;

That said, False is a boolean, not a variant, so it cannot be used as a constant expression of Variant type. Since a variant is a complex type it cannot be expressed as a single constant and, therefore, cannot have a default property.

Per Remy, if you want to ensure that the variant is not saved in the .dfm file when the backing variant is False, you can use the stored directive with a parameterless method which returns False when the variant evaluates to a boolean False. For example :

 property VariantValue : Variant read FVariantValue write FVariantValue stored IsVariantValueStored;

where

function TMyComponent.IsVariantValueStored : Boolean;
begin
  Result := not VarIsType(FVariantValue, varBoolean);
  if not Result then
    Result := FVariantValue;
end;
4
votes

Variant properties cannot have default values.

1
votes

The best thing to do is set

FVariantValue := false;

in the constructor or procedure AfterConstruction; override;