Generic Types
A generic type is one programming construct that adapts to do the same operations for many data types. When you write generic code, it is not necessary to write different implementations for each possible data type.
Example generic class
Class Container[T]
Method Add(item As T)
Dim temp As T
End Method
End Class
Permitted generic constructs
You can make and use generic classes, structures, traits, and procedures. The ViviFire standard libraries supply many frequently used generic constructs that you can use in your code.
Although procedures are not types, you can make and use generic procedures. See Generic Procedures for more information.
How generic types help
You use generic types to declare some different programming elements, where each one operates on the specified data types. The alternatives to a generic type are:
- One type operates on the object data type.
- A set of different implementations of the type, each coded differently to operate on one data type, for example,
Int32
,String
, or a user-made class or structure.
Generic types are better than these alternatives because of:
- Type safety – Generic types let the compiler do type checking. The compiler can find type errors.
- Performance – It is not necessary for generic types to box and unbox data. Each one is specially made for one data type.
- Decreased code – You write the code in a generic type only one time. If you make implementations of a type for each data type, you must write the same code again and again. Their only differences are the data types they use. But generic types automatically make implementations for each data type.
- Code that you can use again – TODO
- Generic algorithms – TODO
Constraints
You must try to write the code for a generic construct as disconnected from types as possible.
But some functions can be necessary to have for data types supplied to your generic construct.
For example, to compare two items to sort them, their data type must implement the trait Compare
.
To do this, you can add a constraint for the type parameter.
Example of a constraint
The example that follows shows a skeleton of a generic class with a constraint.
The constraint makes it necessary for the type argument to implement Compare
.
Class GenericClass[T] Where T Does Compare
' ...
End Class
If you try to use GenericClass
with a type that does not implement Compare
, the compiler gives an error.
Types of constraints
Your constraint can specify the requirements that follow:
- The type argument must be one in a given branch of inheritance.
- The type argument must be one of a reference type, a value type, or a unit of measure.
- The type argument must implement one or more traits.
- The type argument must have a constructor without parameters.
- The class that uses a trait must inherit from a given class.
If you must specify more than one requirement, you can put a comma between each one.
But if a constraint makes a line of code too long, you can divide it into many constraints.
you can use Where
again and again, each on a different line.
But the shortest constraint can use a type parameter a minimum of one time. Then you must put the requirements in the sequence given above.
- If a sub-type is necessary, use one of the operators
<
or<=
. - If a reference type is necessary, use «
Is Class
». - If a value type is necessary, use «
Is Struct
». - If a unit of measure is necessary, use «
Is Unit
». - If a trait is necessary, use «
Does
». - If a constructor is necessary, use «
Constructor()
». The parentheses are mandatory.
See Where Clause (Generics) for more information.
Examples of many constraints
The examples that follow show a skeleton of a generic class with three constraints on the type parameter.
The type argument must (1) be a reference type, (2) implement Compare
, and (3) have a constructor without parameters.
All three examples are equivalent.
Example 1 uses the shortest construct with Where
on the same line as the start of the class.
Class MyClass[T] Where T Is Class Does Compare Constructor()
' ...
End Class
Example 2 uses the construct with commas between requirements all on one line in the class body.
Class MyClass[T]
Where T Is Class, T Does Compare, T Constructor()
' ...
End Class
Example 3 uses three different lines that start with Where
in the class body.
We wrote the requirements in a sequence different from the other examples.
Class MyClass[T]
Where T Constructor()
Where T Does Compare
Where T Is Class
' ...
End Class