Search code examples
delphigenericstdictionary

Is it possible in Delphi to declare a TDictionary with a Generic value type?


Can Delphi make the following statement?

TDictionary <T, TList <T>>

The compiler doesn't like it:

Undeclared identifier: 'T'

I have added in the uses clause:

System.Generics.Collections;

UPDATE: With this code I have these problems:

interface

uses
  System.Generics.Collections;

type
  TListado = class(TObject)
  private
    FListado: TDictionary<T, V: TList<T>>;
    function GetListado: TDictionary<T,TList<T>>;
    procedure SetListado(const Value: TDictionary<T, TList<T>>);
  public
    property Listado: TDictionary<T,TList<T>> read GetListado write SetListado;
    function ReadItems(Cliente: T):TList<T>;
  end;

I changed the unit code but before it worked, I don't know what I'm failing in.

Undeclared identifier: 'T'


Solution

  • You seem to have a fundamental misunderstanding of how Generics work. I strongly suggest you read the documentation more carefully.

    You are trying to use TDictionary in contexts where specific instantiations of the class are needed. In the code you have shown, the compiler is correct that T is an unknown type with which to instantiate your use of TDictionary.

    Everywhere you are using T, you need to specify an actual type that you want to use with the dictionary, for example:

    interface
    
    uses
      System.Generics.Collections;
    
    type
      TListado = class(TObject)
      private
        FListado: TDictionary<Integer, TList<Integer>>;
        function GetListado: TDictionary<Integer, TList<Integer>>;
        procedure SetListado(const Value: TDictionary<Integer, TList<Integer>>);
      public
        property Listado: TDictionary<Integer, TList<Integer>> read GetListado write SetListado;
        function ReadItems(Cliente: Integer): TList<TInteger>;
      end; 
    

    Otherwise, you will need to declare TListado itself as a Generic class with its own parameter, which you can then use to instantiate TDictionary, and then you can specify a type for that parameter when instantiating TListado, eg:

    interface
    
    uses
      System.Generics.Collections;
    
    type
      TListado<T> = class(TObject)
      private
        FListado: TDictionary<T, TList<T>>;
        function GetListado: TDictionary<T, TList<T>>;
        procedure SetListado(const Value: TDictionary<T, TList<T>>);
      public
        property Listado: TDictionary<T, TList<T>> read GetListado write SetListado;
        function ReadItems(Cliente: T): TList<T>;
      end; 
    
    var
      list: TListado<Integer>;
    begin
      list := TListado<Integer>.Create;
      ...
      list.Free;
    end;