我有一个基础班'它包含一个'功能'接受类型'数组const'如下图所示: -
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;
我有另一个'通用课程'这源于基类' (如上所述)
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;
每次编译此代码时都会出错:
变量类型数组构造函数中的错误参数类型
它指的是错误的?
答案 0 :(得分:4)
您不能将通用参数作为variant open array parameter传递。语言泛型支持根本不能满足这一要求。
您可以做的是将泛型参数包装在变体类型中。例如TValue
。现在,您无法将TValue
个实例作为变量打开数组参数传递,但您可以更改NotifyAll
以接受TValue
的开放数组。
procedure NotifyAll(const AParams: array of TValue);
一旦你有了这个,你可以通过你的通用方法调用它:
NotifyAll([TValue.From<T>(AUser)]);
从根本上说,您在此尝试的是将编译时参数方差(泛型)与运行时参数方差相结合。对于后者,有各种选择。变体开放数组参数就是这样一个选项,但它们与泛型不匹配。我在这里建议的替代方法TValue
确实与泛型有很好的互操作性。
答案 1 :(得分:1)
System.Rtti
单元完全满足您的需求,但并不广为人知:
TValueArrayToArrayOfConst()
和
ArrayOfConstToTValueArray()
所以你的实现应该是:
procedure TEventMulticaster<T>.Notify(AUser: T);
var
ParametersAsTValueArray: array[1 .. 1] of TValue;
begin
ParametersAsTValueArray[1] := TValue.From<T>(AUser);
NotifyAll(TValueArrayToArrayOfConst(ParametersAsTValueArray));
end;
注意事项:
TValueArrayToArrayOfConst()
的结果是一个非拥有容器。它包含由 TValue
容器的源数组支持的内存指针。 ParametersAsTValueArray
处于活动状态,在使用 array of const
时不会被更改。Rtti
过程之一在 TClass
值处理方面存在错误。 TClass
在某个阶段变成了 Pointer
,string.Format()
会中断,因为 Pointer
和 TClass
不是一回事。对所有 TVarRec.VType
执行测试,它们并不多,更不用说 Variant 的 VType
。