如何为TComparison <t>分配预先存在的功能?

时间:2015-09-15 15:40:46

标签: delphi anonymous-function

program Project55;    
{$APPTYPE CONSOLE}
uses
  System.Generics.Defaults;

type
  TestRec<T> = record
    Compare: TComparison<T>;
    CompareI: IComparer<T>;
  end;

var
  TRI: TestRec<Integer>;

begin
  TRI.CompareI:= TComparer<Integer>.Default;
  TRI.Compare:= TRI.CompareI.Compare;  //E2035 Not enough actual parameters
  TRI.Compare:= @TRI.CompareI.Compare; //E2035 Not enough actual parameters
end.

我知道我可以将函数体指定为匿名函数,但为什么我不能指定现有函数?

当然以下作品,但这只是愚蠢的:

  TRI.Compare:= function(const L,R: integer): Integer
  begin
    Result:= TRI.CompareI.Compare(L,R);
  end;

PS。我正在使用Delphi XE7,但我怀疑这个版本很重要。

3 个答案:

答案 0 :(得分:4)

知道fatal error: unexpectedly found nil while unwrapping an Optional value on (item.view as! AllCurrencyList).allccytext.stringValue = "foo"只是一个与IBoutlet具有相同签名的方法的接口,并且匿名方法只是一种方法的接口,您可以执行以下操作。

NSMenu

我在Spring4D中使用这个技巧,以避免在IComparer<T>周围创建一个包装器对象,因为它们是二进制兼容的。{/ p>

答案 1 :(得分:3)

您尝试执行此分配失败,因为无法将接口方法分配给方法引用变量。语言根本不允许这样做。类型不是分配兼容的。有效的赋值源是匿名方法,类方法(实例或类)和单元范围过程。

其他答案中可以看到的技巧都取决于对实施细节的深入了解。这意味着它们可能会发生变化。但就语言而言,不允许你尝试的是什么。

答案 2 :(得分:1)

匿名方法不完全是方法指针。它们被实现为具有单个方法“Invoke”的接口。

可以从匿名方法中提取方法指针,但据我所知,它依赖于匿名方法的当前实现细节,并且可能会受到未来版本delphi的更改。换句话说,我会反对它。这是从巴里凯利的帖子here逐字逐句采取的。 (这比我在这里更彻底地涵盖了这个话题)

procedure MethRefToMethPtr(const MethRef; var MethPtr);
type
  TVtable = array[0..3] of Pointer;
  PVtable = ^TVtable;
  PPVtable = ^PVtable;
begin
  // 3 is offset of Invoke, after QI, AddRef, Release
  TMethod(MethPtr).Code := PPVtable(MethRef)^^[3];
  TMethod(MethPtr).Data := Pointer(MethRef);
end;

根据您的示例,我建议将其作为替代

type
  TestRec<T> = record
    CompareI: IComparer<T>;
    function Compare(const L, R : T) : Integer;
  end;
[...]
function TestRec<T>.Compare(const L, R : T) : Integer;
begin
  Result := CompareI.Compare(L,R);
end;

但是,它可能/可能不适用于您目前的情况。