There is a certain class, let's say:

TListEx<T: TBaseClass> = class ... .... procedure Sort; .... end; 

and there is some TNotifyEvent event where you need to call this Sort:

 procedure TMyForm.ListEvent(Sender: TObject); begin .... (Sender as ??????).Sort; end; 

Question: what should be written instead of "?????" ? If you write TListEx<TBaseClass> , then when you call the method with Sender = TListEx<TExtClass> ( TExtClass = class(TBaseClass) ), you still get an error of the type 'invalid class typecast'.

But is the method still common? How to get around this trouble?

More precisely, at the moment I decided this as TListEx<TBaseClass>(Sender).Sort , but I would still like to do it through as for reliability.

  • you would add a playable example so that you don’t have to write classes for you (the minimum playable example ) - teran
  • one
    formally, TListEx<TBaseClass > and TListEx<TExtClass> are completely different things (they have no common ancestor). Your parameter is inherited, not the class. Therefore, it does not lead him. Now, if you had written TListEx<T> = class(TListEx) with the sort() method and would lead to it, then everything would be fine. - teran
  • Yes, this is probably a good idea, but in my case it does not work, because Sort uses T field values; - Alekcvp
  • one
    you declare it abstract in the base class. and TListEx<T> in TListEx<T> - teran
  • For sure. I think you can in response. - Alekcvp

1 answer 1

As I understand it, we have the following.
Classes options:

 TBaseClass = class(TObject) end; TExtClass = class(TBaseClass) end; 

generic class list:

 TListEx<T> = class(TObject) public procedure Sort(); end; 

and the method that takes an argument is a list:

 procedure test(sender: TObject); begin writeln(sender.ClassName); (sender as TListEx<BaseClass>).sort(); // invalid typcast end; 

test method call:

 var l : TListEx<TExtClass>; l := TListEx<TExtClass>.Create(); test(l); 

When using generics, the compiler creates a class for each of the parameters. As a result, we get 2 completely independent classes TListEx<TBaseClass> and TListEx<TExtClass> without a common ancestor. Here only classes of parameters are inherited, therefore casting cannot be performed.

You can enter a base list class.

 TListEx = class(TObject) procedure Sort(); virtual; abstract; end; 

And inherit a typed list from it. Then, when casting a type, knowledge of the T parameter will not be required:

 TListEx<T> = class(TListEx) public procedure Sort(); override; end; .... (Sender as TListEx).Sort(); 
  • for some reason, I have a feeling that something is wrong here, and it can be done differently. - teran