Pregunta

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.

¿Fue útil?

Solución

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top