Navigation: Clarion.Net (Clarion#) > Clarion# Language Extensions > Generics >====== Generics ====== | |
Generics in .NET programming refers to a class that is not related to any specific Type, but is still used in a Type-Safe manner. A perfect example of where Generics are useful is with collections of items (integers, strings, Orders etc.). We can create a generic collection than can handle any Type in a generic and Type-Safe manner. For example, we can have a single array class that we can use to store a list of Users or even a list of Products, and when we actually use it, we will be able to access the items in the collection directly as a list of Users or Products, and not as objects.
The use of generic classes is supported in Clarion#.
To use generic types/methods, specify generic arguments (types) in angle brackets.( <;'>).
Examples:
Aa &List<;Int32> !declaration of variable with generic List type with Int32 argument |
bb.cc<;String>('aaa') !generic method call cc with generic String argument |
There are two restrictions:
1. Arrays can't be used as a generic argument
2. All .Net reference types are considered as reference and .Net value-types are considered as values. Using of types with & (such as &LONG) in generic arguments are not supported
Declaration of generics
To declare a generic CLASS, STRUCT, or INTERFACE you should add generic parameters in angle brackets (e.g., <; >) just after the appropriate keyword. Constraints for generic parameters can be specified with a WHERE(') clause. The list of WHERE clauses (without any delimiters) should be placed before all attributes.
The syntax of the WHERE clause is as follows:
WHERE(<;generic argument name>=(constraint1,constraint2',constraintN)
Where constraint has the following syntax:
NEW|CLASS|STRUCT|<;type>
NEW | The generic argument should have default constructor |
CLASS | The generic argument should be reference type |
STRUCT | The generic argument should be value type |
<;type> | The generic argument should be inherited from the <;type> |
In the generic method definition the class label uses the following syntax:
Notes:
1.CLASS and STRUCT constraints can't be used simultaneously.
2.If <;type> is a STRUCT or CLASS, then STRUCT and CLASS constraints can't be used.
3.When calling the generic method, the explicit <;type> is superfluous, if the passed parameter is already of the desired class.
In the method definition for a Generic the class label has the following syntax:
Name <;generic parameter1,', generic parameterN>
Example:
PROGRAM
NAMESPACE qqq
USING System
aa CLASS<;T,V> WHERE(T=ICloneable)
mm PROCEDURE
bb PROCEDURE(T b)
vv PROCEDURE(T b,V e)
INLINE
CODE
MESSAGE(b.Clone())
END
END
CODE
aa<;T,V>.mm PROCEDURE
ee &ICloneable
bb1 T
CODE
ee = bb1
SELF.bb(bb1)
MESSAGE(bb1.Clone())
aa<;T,V>.bb PROCEDURE(T b)
CODE
To declare generic methods place the generic parameters of the procedure in <;'> and add constraints (WHERE clause before any attributes of the procedure)
Example:
Bb PROCEDURE<;T>(T arg) WHERE(T=NEW)
Current restrictions in using generic parameters:
1. If T is a generic parameter then the following declarations are equivalent:
Clarion# | C# |
Aa T | T aa; |
No instance is created and no constructor is called. It's just a declaration of a variable.
The following declaration syntax:
Aa &T
is currently not supported.
2. If the left or right part of the assignment statement has a type T, where T is a generic parameter, you need to use the = assignment operator (not &.
For example:
Aa T
Bb T
CODE
AA = Bb
DEFAULTOF
You can also generate a default value for a type in a generic declaration.
The special expression:
DEFAULTOF (<;type>)
is used for this purpose.
The expression generates a default value for the corresponding type. For value-types, it's value with zeros (0) and for reference types it's just a null reference. For more information see the default keyword in C# documentation.
Example:
A T
CODE
A=DEFAULTOF(T)