编辑,澄清了这个问题,因为我将其简化了太多,从而消除了我实际面临的问题
我有一位代表,在机构中实施了很长时间 因此我不想在我正在使用它的函数中声明它。
type
TTaskDelegate<A, B> = reference to procedure(const Data: IData);
//-----------^^^^^^ note the type parameters here
//-But no type parameters here---------------------------^^^^^^
委托被声明为,以便我可以将它存储在看起来像的记录中:
TMultiDelegate = record
strict private
fAA: TTaskDelegate<TOmniValue, TOmniValue>;
fAB: TTaskDelegate<TOmniValue, IOmniBlockingCollection>;
fBA: TTaskDelegate<IOmniBlockingCollection, TOmniValue>;
fBB: TTaskDelegate<IOmniBlockingCollection, IOmniBlockingCollection>;
fSimple: TSimpleTaskDelegate;
fOutputCount: Integer;
function GetDelegateType: TDelegateType;
public
constructor Init(AA: TTaskDelegate<TOmniValue, TOmniValue>; const OutputCount: integer = 1); overload;
constructor Init(AB: TTaskDelegate<TOmniValue, IOmniBlockingCollection>; const OutputCount: integer = 1); overload;
.....
类型参数还可以提醒输入和输出类型的泛型过程的实现者。
因为类型参数不在方法标题的其余部分重复,所以在声明函数时必须保留它们。
出于这个原因,斯特凡的回答不起作用。
将其声明为单位常量(或单位变量)不起作用 由于其通用签名,将其声明为单元程序也不起作用 以下代码无法编译:
示例A
const
Test: integer = 0;
const
DoesNotCompile: TTaskDelegate<TOmniValue, TOmniValue> =
procedure(const Data: IData)
begin
//Do stuff
end;
E2026预期的常量表达式
//This variant will not compile either.
procedure DoStuff<TOmniValue, TOmniValue>(const Data: IData)
begin
//DoStuff
end;
当我将它包装在一个函数中时,它确实有效。
样本B
function ListSplitterDelegate: TTaskDelegate<TOmniValue, TOmniValue>;
begin
Result:=
procedure(const Data: IData)
begin
//Do stuff
end;
end;
以这种方式做这件事感觉有点多余 有没有办法避免将通用匿名函数包装在另一个函数中?
答案 0 :(得分:2)
已更新至已修改的问题:
将其声明为常规程序应该可以正常工作:
procedure Whatever_TOmniValue_TOmniValue(const Data: IData);
begin
//Do stuff
end;
答案 1 :(得分:0)
你想做的事是不可能的。匿名方法是有状态的,引用计数的对象本质上不是常数。匿名方法的赋值产生一个闭包,其状态在其环境变化时不断被检查和修改。它在某些方面与其他编译器管理类型一样,如动态数组,由于某些类似的原因也不能是const
。
您创建ListSplitterDelegate
函数的解决方案可能是您可以做的最好的。否则,您需要将DoesNotCompile
声明为变量并在运行时分配它。
var
CompilesOk : TTaskDelegate<TOmniValue, TOmniValue>;
//...
initialization
CompilesOk := procedure(const Data: IData<TOmniValue, TOmniValue>)
begin
//Do stuff
end;
显然,这有一个问题,CompilesOk
可以被覆盖(出于多种原因,这是一个坏主意)。 ListSplitterDelegate
是最佳解决方案,如果您需要这是一个匿名方法。我不认为您需要这是一个匿名方法,因为可以将常规方法分配给reference to
类型。
SSCCE演示(使用您更新的代码示例和签名):
unit Unit1;
interface
type
IData = interface
end;
TOmniValue = record
end;
TTaskDelegate<A,B> = reference to procedure(const Data: IData);
TMultiDelegate = record
strict private
fAA: TTaskDelegate<TOmniValue, TOmniValue>;
public
constructor Init(AB: TTaskDelegate<TOmniValue, TOmniValue>);
procedure DoIt;
end;
implementation
constructor TMultiDelegate.Init(AB: TTaskDelegate<TOmniValue, TOmniValue>);
begin
fAA := AB;
end;
procedure TMultiDelegate.DoIt;
var dat: IData;
begin
fAA(dat);
end;
end.
主要:
program Project1;
{$APPTYPE CONSOLE}
{$R *.res}
uses
Unit1 in 'Unit1.pas';
procedure DoSomething(const Data : IData);
begin
writeLn('foo');
end;
var
tmd : TMultiDelegate;
begin
tmd.Init(DoSomething);
tmd.DoIt;
ReadLn;
end.
编译好。按预期运行。在Delphi XE2中测试。