C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Next: In this example, the letter T denotes a type that is only known based on the calling location.
And: The program can act upon the instance of T like it is a real type, but it is not.
C# program that describes generic class
using System;
class Test<T>
{
T _value;
public Test(T t)
{
// The field has the same type as the parameter.
this._value = t;
}
public void Write()
{
Console.WriteLine(this._value);
}
}
class Program
{
static void Main()
{
// Use the generic type Test with an int type parameter.
Test<int> test1 = new Test<int>(5);
// Call the Write method.
test1.Write();
// Use the generic type Test with a string type parameter.
Test<string> test2 = new Test<string>("cat");
test2.Write();
}
}
Output
5
cat
Note: The syntax form for the declaration uses the <T> characters after the method name but before the formal parameter list.
Example: This program shows a generic method. The type parameter is customarily the type T or V or TValue or similar.
GetInitializedList: This is a generic method that constructs a special List. It uses a type parameter with name T.
Info: The first parameter to the GetInitializedList method is also a value of type T.
C# program that declares generic method
using System;
using System.Collections.Generic;
class Program
{
static List<T> GetInitializedList<T>(T value, int count)
{
// This generic method returns a List with ten elements initialized.
// ... It uses a type parameter.
// ... It uses the "open type" T.
List<T> list = new List<T>();
for (int i = 0; i < count; i++)
{
list.Add(value);
}
return list;
}
static void Main()
{
// Use the generic method.
// ... Specifying the type parameter is optional here.
// ... Then print the results.
List<bool> list1 = GetInitializedList(true, 5);
List<string> list2 = GetInitializedList<string>("Perls", 3);
foreach (bool value in list1)
{
Console.WriteLine(value);
}
foreach (string value in list2)
{
Console.WriteLine(value);
}
}
}
Output
True
True
True
True
True
Perls
Perls
Perls
Next: This program uses 3 classes that demonstrate different ways of constraining type parameters.
Ruby: The Ruby class requires that its type parameter implement IDisposable. We can thus call the Dispose method or using statement.
UsingPython: This type demands that its type parameter be a struct. Ints are structs so you could use Python<int> as the constructed type.
StructPerl: This type requires that its type parameter V be a reference type (a class). It also requires a public parameterless constructor.
ConstructorC# program that uses generic type constraints
using System;
using System.Data;
/// <summary>
/// Requires type parameter that implements interface IDisposable.
/// </summary>
class Ruby<T> where T : IDisposable
{
}
/// <summary>
/// Requires type parameter that is a struct.
/// </summary>
class Python<T> where T : struct
{
}
/// <summary>
/// Requires type parameter that is a reference type with a constructor.
/// </summary>
class Perl<V> where V : class, new()
{
}
class Program
{
static void Main()
{
// DataTable implements IDisposable so it can be used with Ruby.
Ruby<DataTable> ruby = new Ruby<DataTable>();
// Int is a struct (ValueType) so it can be used with Python.
Python<int> python = new Python<int>();
// Program is a class with a parameterless constructor (implicit)
// ... so it can be used with Perl.
Perl<Program> perl = new Perl<Program>();
}
}
Also: It describes the algorithm used by the language compiler. But these details are not useful for most programs.
Tip: Do not rely on language specification details in your program. Most developers do not study language specifications at length.
Note: You can often omit the type parameter, but not where the method call cannot be determined from the context.
Tip: We rarely need to make our own generic types now that the .NET Framework already contains so many useful ones.
Constructed type: This is another term for a generic type—it refers to a type with a type parameter.
Open type: This is also a term for a generic type. It is a type that has type parameters.
Closed type: As opposed to an open type, a closed type is one that does not have type parameters.
Unbound type: An unbound type is declared by a type declaration, but is not actually a type.
Bound type: A bound type is one of two types—a regular type or a constructed type. It is a type of types.