Search code examples
delphigenericsdelphi-xe2delphi-xe5delphi-xe4

Typecast Generic type to other type


i have a base class

 TEventMulticaster = class(Tobject)
 public
   procedure Notify(aMap: WideString);
 end;

 procedure TEventMulticaster.Notify(aMap: WideString);
 begin
  // Do something 
 end;

And a derived generic class

  TEventMulticaster<T> = class(TEventMulticaster)
   public
     procedure Notify(aMap: T ); reintroduce;
   end;


  procedure TEventMulticaster<T>.Notify(aMap: T);
  begin
    inherited Notify(aMap)  // ERROR
  end;

when base class Notify is call it give me error "Incompatible types: 'WideString' and 'T'" and when i do **Notify(WideString(aMap))** it says invalid typecast

my question is how can i type cast generic type to "WideString" so that i can call base class notify


Solution

  • procedure TEventMulticaster<T>.Notify(aMap: T);
    begin
      inherited Notify(aMap);
    end;
    

    Here you have aMap which is a generic argument, of type T. The type T has no constraints on it. It can be any type. You are seeking to convert aMap to WideString. The compiler simply has no way to do that. There is no over-arching conversion that can take an argument of arbitrary type and convert it to WideString.

    You could push aMap into a TValue, and then call the ToString method of TValue. The compiler will at least be satisfied with this:

    inherited Notify(TValue.From<T>(aMap).ToString);
    

    This might do what you expect. Or perhaps not. It all depends upon what T happens to be. If T is a fundamental type like Integer or string then TValue.ToString will almost certainly do what you expect. If T is more esoteric then who knows whether this code will behave as you expect. You certainly have not given us any indication as to how the arbitrary type is to be converted to text.


    The thing that I suspect you are not grasping about generics is that the compiler has to know how to compile the method without knowing what the generic type is. In comments you state that:

    aMap is not of type class

    Whilst you might know that, the compiler does not. From the perspective of the compiler, T can be anything at all. Generics are very different from Smalltalk/C++ templates where the compilation happens after instantiation.

    The generics functionality does allow you to apply constraints to your generic type. However, these are quite limited. You cannot apply a constraint that says, type T will have a well-defined implicit conversion to WideString.

    As I have said to you before, I sense that you are struggling with your understanding of generics. I feel that it would be more productive for you to present the underlying problem rather than you proposed solution.


    One final point. The WideString type is a wrapper around the COM BSTR string type. In modern Unicode aware Delphi you use WideString just when writing interop code with COM. You should be using string rather than WideString. The string type is an alias for UnicodeString, the native Delphi Unicode string type.