Delphi: a generic list of generic descendants and getting a generic parameter as a parameter

I struggle a bit with understanding generics and how they can and cannot be used.

I have a generic TControlMediator class:

TControlMediator<C, T> = class private FMediatedComponent: C; public constructor Create(ComponentToMediate: C); function GetValue: T; virtual; abstract; procedure SetValue(Value: T); virtual; abstract; property MediatedControl: C read FMediatedComponent; end; 

Then I subclass "concret" for each type of control that I want to mediate:

 TEditMediator = class(TControlMediator<TEdit, string>) public function GetValue: string; override; procedure SetValue(Value: string); override; end; 

So far, everything is working fine. Problems arise, though, when I need a descendant of TControlMediator, or taking TControlMediator as a method parameter:

 TViewMediator = class private FControlMediators: TList<TControlMEdiator<C, T>>; public procedure registerMediator(AControlMediator: TControlMediator<C, T>); procedure unregisterMediator(AControlMediator: TControlMediator<C, T>); end; 

The compiler stops with fatal errors:

 [DCC Error] mediator.pas(23): E2003 Undeclared identifier: 'C' [DCC Error] mediator.pas(28): E2007 Constant or type identifier expected 

Does anyone have any clues on how this should be done?

+3
source share
1 answer

Delphi does not have covariance or contravariance on its common types. Your generic types should use the actual types as parameters. In other words, it is:

 TViewMediator = class private FControlMediators: TList<TControlMEdiator<C, T>>; public procedure registerMediator(AControlMediator: TControlMediator<C, T>); procedure unregisterMediator(AControlMediator: TControlMediator<C, T>); end; 

... will not work because C and T are not typical arguments of type TViewMediator or real types.

TControlMediator<TEdit, string> is a type. TList<TControlMEdiator<C, T>> when there are no types of C or T in scope is not a type. You cannot use a type type placeholder when creating an instance of a generic type, unless these placeholders are included in general arguments in the containing general type or method.

+6
source

All Articles