0

Imagine I have a class like this:

type TFunctionWrapper<T1,T2> = class
private
  FFunc : TFunc<T1,T2>;
public
  constructor Create(AFunc : TFunc<T1,T2>);
  function Apply(AValue : T1) : T2;
end;

with implementation

constructor TFunctionWrapper<T1,T2>.Create(AFunc : TFunc<T1,T2>);
begin
  FFunc := AFunc;
end;

function TFunctionWrapper<T1,T2>.Apply(AValue : T1) : T2;
begin
  Result := FFunc(AValue);
end;

How can i test, if the assigned functions are the same? Function references cannot be equated with F1 = F2 as it result in a compiler error:

[dcc32 Error] Project1.dpr(37): E2035 Not enough actual parameters,

which makes pretty good sense.

Anyway, the problem remains: How do you test if assigning a function to a field work as intended, without just testing if the field and the function return the same result on the same input?

Undreren
  • 2,811
  • 1
  • 22
  • 34

1 Answers1

0

These are reference method types, declared with reference to. They are implemented as interfaces, automatically created and managed by the compiler.

So, you can test for equality by casting to an interface, and using interface equality:

IInterface(Pointer(@F1)^) = IInterface(Pointer(@F2)^)

This is a little bit gnarly, and thanks to Stefan Glienke's answer here for showing me how: https://stackoverflow.com/a/22645248/505088

But be warned that this might not give the results that you expect. For instance this program:

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

function Foo(Value: Integer): Integer;
begin
  Result := Value;
end;

var
  F1, F2: TFunc<Integer, Integer>;

begin
  F1 := Foo;
  F2 := Foo;
  Writeln(IInterface(Pointer(@F1)^) = IInterface(Pointer(@F2)^));
  Readln;
end.

outputs FALSE. That's because the compiler creates two distinct anonymous methods for F1 and F2. The compiler could, in theory, detect that both anonymous methods call the same function, in the same context, and optimise this code to use the a single anonymous method. But the compiler does not do that.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490