<T> is a notation for type parameters.

Syntax

<T>
Note: This topic applies to ABL generic types. For information on .NET generic types, see Reference .NET generic types in Use .NET Classes in ABL Applications.

Generic type

A generic type is an object-oriented type (for a class or interface) that accepts one or more type parameters, allowing the class to defer the specification of such parameters until the class is declared and instantiated by a client of the class. This allows code for the class or interface to be written once, instead of having to write multiple classes or interfaces for each required type. The implementation of generic types also eliminates the cost of having to cast references at runtime.

A list is a common example for a generic type. A list generic type has common functionality for any type of list, and you can store any kind of objects, or related objects, depending on the requirements, without having to write a different class for each type of object you want to store in the list.

Note: User-defined generic types are not supported.

Type parameter

A type parameter is defined inside angle brackets (<>) and is given a name (usually a single letter) and a type for each type parameter, which defines the constraint for the types of objects the generic type can work with. A generic type can have multiple type parameters, defined inside the angle brackets and separated by commas (,). The type parameter is used as a placeholder in the places where a concrete type would normally be specified, to indicate the actual type for the instance of the generic type. For example, the following is the declaration of the Progress.Collections.List<T> class:
Progress.Collections.List<T as Progress.Lang.Object>
This generic class contains one type parameter T, defined as Progress.Lang.Object. This allows you to declare an instance of such a class using any object that is compatible with the parameter type, in this case, Progress.Lang.Object.

Note that a generic type is generally referred to with the type parameter notation, for instance List<T>.

Type parameters are used in the generic type wherever a concrete type is used. For example, the following members of the List<T> type show where the type parameter is used:
METHOD PUBLIC VOID Add(element AS T).

METHOD PUBLIC T Get(index AS INTEGER).
Given a class type named Animals, in a list of Animals, then Add() would accept objects that are compatible with the type Animals, and Get() would return an object of type Animals.

Type arguments

A type argument is the type you specify on the client of the generic class or interface. When using a generic type, you must specify the same number of type arguments as there are type parameters defined in the generic type. That is, you cannot instantiate a generic type without specifying type arguments. For example:
var List<Ant> ListOfAnts.

var List<Person> ListOfPeople.
This example shows two different instances of the type List<T>, using different type arguments: Ant and Person. This allows the client code to have List<Ant>, referred to as a “List of Ant”, and List<Person>, referred as a “List of Person”.

Referencing a generic type like this is referred to as "constructing the type". Therefore, a reference to a generic type that specifies a particular set of data types for its type parameters is referred to as a "reference to its constructed type name".

The compiler requires that each type argument supplied has an "is-a" relationship to the corresponding type parameter; that is, the argument must either be, inherit from, or implement the type parameter.

Since the List<T> type defines a type parameter of type Progress.Lang.Object, that allows List<T> to be supplied with any type of object-oriented ABL object as a type argument, but not any scalar types.

After you declare a variable using the constructed type name, the compiler ensures that the type of the type argument is used wherever the generic class refers to the type parameter in its API.

Therefore, the following code is allowed as the Add() method requires a Person for a List<Person>, and the Get() method returns a Person.
var List<Person> ListOfPeople.
var Person currPerson = new Person("John Smith").
ListOfPeople:Add(currPerson).
currPerson = ListOfPeople:Get(1).
If you change List<Person> to List<Ant>, then both the Add() and Get() calls would not compile as the Person and Ant types are not the same.
The compatibility rules for object-oriented ABL types applies to generic types, except that the type arguments must match exactly. For example, this statement is allowed, as List<T> implements IList<T> and the type arguments exactly match:
var IList<Ant> rListOfAnts = new List<Ant>.
However, assuming Ant has Insect in its hierarchy, whether as a super class or an interface, this statement is not allowed, as the type argument does not exactly match:
var IList<Insect> rListOfInsects = new List<Ant>.
Even though Ant is-a Insect, a List<Ant> does not implement an IList<Insect>.

The restriction also applies when you need to cast an object (with CAST or DYNAMIC-CAST).