RAD Studio (Common)
ContentsIndex
PreviousUpNext
Overview of Generics

Delphi for .NET supports the use of generics, also known as parameterized types.

The term generics is a collective noun that describes the set of things in the platform that can be parameterized by type using the new support in .NET 2.0. Generics can refer to generic types, generic methods, or (for Delphi) generic procedures and generic functions.  

Generics are a set of abstraction tools that permit the decoupling of an algorithm (such as a method, procedure or function) or a data structure (such as a class, interface or record) from one or more concrete types that the algorithm or data structure uses. 

A method or data type that uses other types in its definition can be made more general by substituting one or more concrete types with type parameters. Then you add those type parameters to a type parameter list in the method or data structure declaration. This is similar to the way that you can make a procedure more general by substituting instances of a literal constant in its body with a parameter name, and adding the parameter to the parameter list of the procedure. 

For example, a class (TMyList) that maintains a list of objects (of type TObject) can be made more reusable and type-safe by substituting uses of TObject with a type parameter name (such as 'T'), and adding the type parameter to the class's type parameter list so that it becomes TMyList<T>. 

Concrete uses (instantiations) of a generic type or method can be made by supplying type arguments to the generic type or method at the point of use. The act of supplying type arguments effectively constructs a new type or method by substituting instances of the type parameter in the generic definition with the corresponding type argument.  

For example, the list might be used as TMyList<Double>. This creates a new type, TMyList<Double>, whose definition is identical to TMyList<T> except that all instances of 'T' in the definition are replaced with 'Double'. 

It should be noted that generics as an abstraction mechanism duplicates much of the functionality of polymorphism, but with different characteristics. Since a new type or method is constructed at instantiation time, you can find type errors sooner, at compile time rather than run time. This also increases the scope for optimization, but with a trade-off - each instantiation increases the memory usage of the final running application, possibly resulting in lower performance.

For example, TSIPair is a class holding two data types, String and Integer:

type
  TSIPair = class
  private
    FKey: String;
    FValue: Integer;
  public
    function GetKey: String;
    procedure SetKey(Key: String);
    function GetValue: Integer;
    procedure SetValue(Value: Integer);
    property Key: TKey read GetKey write SetKey;
    property Value: TValue read GetValue write SetValue;
  end;

To make a class independent of data type, replace the data type with a type parameter.

type
  TPair<TKey,TValue>= class   // declares TPair type with two type parameters

private
    FKey: TKey;
    FValue: TValue;
  public
    function GetKey: TKey;
    procedure SetKey(Key: TKey);
    function GetValue: TValue;
    procedure SetValue(Value: TValue);
    property Key: TKey read GetKey write SetKey;
    property Value: TValue read GetValue write SetValue;
  end;

type
  TSIPair = TPair<String,Integer>; // declares instantiated type
  TSSPair = TPair<String,String>; // declares with other data types
  TISPair = TPair<Integer,String>;
    TIIPair = TPair<Integer,Integer>;
    TSXPair = TPair<String,TXMLNode>;

Parameterized types are supported by .NET 2.0 or later, but are not supported by .NET 1.1 or before. 

 

 

 

Instantiation timing: 

On .NET, instantiation is processed by the run time environment.

Copyright(C) 2008 CodeGear(TM). All Rights Reserved.
What do you think about this topic? Send feedback!