Identify constraints on generic type parameters
- Last Updated: March 30, 2020
- 2 minute read
- OpenEdge
- Version 12.2
- Documentation
The complete formal declaration for a generic type can also include constraints on the .NET data types that are allowed for each of its type parameters. These constraints place limits on the choice of data types that you can substitute for a given type parameter.
If there are no constraints on a type
parameter, when a generic class is compiled, the .NET compiler
treats the type parameter as a System.Object. Therefore,
the methods and properties defined in the generic class can operate
on the type parameter only in ways that are allowed for a System.Object,
which is a very limited set of operations. By constraining the type
parameter, it increases the number of allowable operations to what
are supported by the constraining types and all types in their inheritance
hierarchy.
Therefore, generic classes and interfaces often have constraints on their type parameters. It gives the coder of the generic type more flexibility and some type checking even before the actual type is supplied in a constructed type name.
A
given constraint might allow you to substitute only .NET value
types for a given type parameter, which would allow you to substitute
the ABL INTEGER or .NET "System.Drawing.Size" type.
A type with this constraint is the SettablePropertyValue<T> generic
class in the Microsoft.EnterpriseManagement.Administration namespace.
Note that constraints on a generic type parameter are introduced
in C# by the where keyword (shown in bold):
|
For another example, this is a C# generic class
type that constrains the TEmployee type parameter
to be replaced by an Employee object or any object
that inherits from Employee:
|
A .NET generic type parameter can also
be defined with multiple constraints to identify a particular subset
of .NET types that you can substitute for a given type parameter
in a constructed type name. This example shows the C# definition
for the System.Nullable<T> generic structure
type:
|
Thus, System.Nullable<T> defines
two constraints on the type parameter T, where
the .NET type you substitute for T must be
a value type with a default constructor (a constructor with no parameters).
The following table lists every possible
type parameter constraint using C# syntax, where the where keyword identifies
one or more constraints on some type parameter, Tparm,
and the description shows one or more ABL constructed type examples
that satisfy each constraint.
| Constraint | Description |
|---|---|
where Tparm :
struct
|
Tparm must be a value type, and can be any value type except a
nullable type (System.Nullable).For example, valid ABL
references to a generic type,
|
where Tparm :
class
|
Tparm must be a reference type, which can be any class,
interface, delegate, or array type. For example, a valid ABL reference to a
generic type,
|
where Tparm :
new()
|
Tparm must have a default public constructor (without
parameters) For example, a valid ABL reference to a generic type,
|
where Tparm : BaseClassName
|
Tparm must be, or derive from, the class specified by
BaseClassName. For example, a valid ABL reference to a
generic type defined as |
where Tparm : InterfaceName
|
Tparm must be, or must implement, the interface specified by
InterfaceName. The constraining interface can also be
generic. For example, a valid ABL reference to a generic type defined as
|
where Tparm : Uparm
|
The type argument that you substitute for Tparm
must be, or must derive from, the type argument that you substitute for another type
parameter, Uparm. This is called a naked type constraint. For
example, a valid ABL reference to a generic type defined as
|
|
Tparm can by constrained by one or more of the previously listed
constraints (constraint), as long as the new()
constraint is listed last.For example, a valid ABL reference to a generic type
defined as |