Delphi - 如何将Generic参数传递给接受const参数数组的函数

时间:2014-10-27 09:33:56

标签: delphi generics delphi-xe4

我有一个基础班'它包含一个'功能'接受类型'数组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;

每次编译此代码时都会出错:

  

变量类型数组构造函数中的错误参数类型

它指的是错误的?

2 个答案:

答案 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;

注意事项:

  1. TValueArrayToArrayOfConst() 的结果是一个非拥有容器。它包含由 TValue 容器的源数组支持的内存指针。 ParametersAsTValueArray 处于活动状态,在使用 array of const 时不会被更改。
  2. 这 2 个 Rtti 过程之一在 TClass 值处理方面存在错误。 TClass 在某个阶段变成了 Pointerstring.Format() 会中断,因为 PointerTClass 不是一回事。对所有 TVarRec.VType 执行测试,它们并不多,更不用说 Variant 的 VType