I have a 'Base class' which contain a 'function' that accept parameter of type 'Array of const' as shown below:-
type
TBaseClass = class(TObject)
public
procedure NotifyAll(const AParams: array of const);
end;
procedure TBaseClass.NotifyAll(const AParams: array of const);
begin
// do something
end;
I have another 'Generic class' that is derived from the 'base class' ( defined above )
type
TEventMulticaster<T> = class(TBaseClass)
public
procedure Notify(AUser: T); reintroduce;
end;
procedure TEventMulticaster<T>.Notify(AUser: T);
begin
inherited NotifyAll([AUser]); ERROR HERE
end;
Every time I compile this code it gives error saying:
Bad argument type in variable type array constructor
What does it referring to be wrong?
You cannot pass a Generic argument as a variant open array parameter. The language Generics support simply does not cater for that.
What you can do instead is wrap the Generic argument in a variant type, for instance TValue
. Now, you cannot pass TValue
instances in a variant open array parameter either, but you can change NotifyAll()
to accept an open array of TValue
instead:
procedure NotifyAll(const AParams: array of TValue);
Once you have this in place, you can call it from your Generic method like so:
NotifyAll([TValue.From<T>(AUser)]);
Fundamentally, what you are attempting to do here is combine compile-time parameter variance (Generics) with run-time parameter variance. For the latter, there are various options. Variant open array parameters are one such option, but they do not play well with Generics. The alternative that I suggest here, TValue
, does have good interop with Generics.
The System.Rtti
unit has something exactly for you needs, but not widely known:
TValueArrayToArrayOfConst()
and
ArrayOfConstToTValueArray()
So your implementation should be:
procedure TEventMulticaster<T>.Notify(AUser: T);
var
ParametersAsTValueArray: array[1 .. 1] of TValue;
begin
ParametersAsTValueArray[1] := TValue.From<T>(AUser);
NotifyAll(TValueArrayToArrayOfConst(ParametersAsTValueArray));
end;
Notes:
TValueArrayToArrayOfConst()
's result is a non-owning container. It contains memory pointers backed by the source array of the TValue
container. ParametersAsTValueArray
is alive and not being altered while the array of const
is used.Rtti
procedures has a bug with regard to TClass
values processing. TClass
becomes a Pointer
on some stage, and string.Format()
breaks because Pointer
and TClass
are not the same thing. Perform tests on all TVarRec.VType
, they are not so many, much less that Variant's VType
.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With