We use a TList<TFunc<Boolean>>
with some function ... of object
s in it and now want to Remove()
some of the entries again. But it doesn't work because obviously you simply can not compare these reference to ...
thingies reliably.
Here's some test code:
program Project1;
{$APPTYPE CONSOLE}
uses
Generics.Defaults,
SysUtils;
type
TFoo = class
strict private
FValue: Boolean;
public
constructor Create();
function Bar(): Boolean;
end;
{ TFoo }
function TFoo.Bar: Boolean;
begin
Result := FValue;
end;
constructor TFoo.Create;
begin
inherited;
FValue := Boolean(Random(1));
end;
function IsEqual(i1, i2: TFunc<Boolean>): Boolean;
begin
Result := TEqualityComparer<TFunc<Boolean>>.Default().Equals(i1, i2);
end;
var
s: string;
foo: TFoo;
Fkt1, Fkt2: TFunc<Boolean>;
begin
try
Foo := TFoo.Create();
WriteLn(IsEqual(Foo.Bar, Foo.Bar)); // FALSE (1)
WriteLn(IsEqual(Foo.Bar, TFoo.Create().Bar)); // FALSE (2)
Fkt1 := function(): Boolean begin Result := False; end;
Fkt2 := Fkt1;
WriteLn(IsEqual(Fkt1, Fkt2)); // TRUE (3)
Fkt2 := function(): Boolean begin Result := False; end;
WriteLn(IsEqual(Fkt1, Fkt2)); // FALSE (4)
Fkt2 := function(): Boolean begin Result := True; end;
WriteLn(IsEqual(Fkt1, Fkt2)); // FALSE (5)
FreeAndNil(Foo);
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln(s);
end.
We tried virtually everything, = operator, comparing pointers, etc..
We even tried some really nasty things like repeatedly casting to PPointer
and dereferencing until we get equal values, but that of course didn't yield satisfying results either =).
- Case (2), (4) and (5) are OK, as there are in fact distinct functions.
- Case (3) is trivial and OK, too.
- Case (1) is what we want to detect, and this is what we can't get to work.
I fear, Delphi stealthily creates two distinct anonymous functions that forward the call to Foo.Bar
. In this case we'd be completely powerless, unless we wanted to wade through a morass of unknown memory... and well, we don't.