I have a list of generics in which I want to put either some records or some classes
TMyList<T> = class
private
fCount: Cardinal;
fItems: array of T;
public
constructor Create(aSize: Integer);
procedure UpdateItem(const x: T);
end;
But I can't have the compiling
procedure TMyList<T>.UpdateItem(const x: T);
var
I: integer;
begin
for I := 0 to fCount - 1 do
if fItems[I] = x then begin // <- error E2015
//do update
break;
end;
end;
It works for classes with this declaration: TMyList<T : class> = class
, but then it can't hold records anymore.
Of course, for the record I declare class operator Equal(Left, Right : TMyRecord) : Boolean;
so that MyRecord1 = MyRecord2
would compile.
This can never be made to work using the =
operator. The reason is that generic constraints are not rich enough to specify the availability of operators. You simply cannot use the =
operator on generic operands.
You can do so if you constrain the operands to be a class, because a classes are references, and the compiler knows how to compare references for equality. Basically the compiler needs to know how to generate the code when it compiles the generic class. Unlike C++ or Smalltalk templates, with generics the compiler does not wait until instantiation to compile the code.
If you want to use a custom comparer then you will need to supply that explicity. Which is rather frustrating, I know. If you can make do with the default comparer you can use:
TEqualityComparer<T>.Default
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With