Making Generic Classes
The section on collection classes in Lesson 16 explained how to use generic collection classes.
For example, the following code defines a list that holds
Employee objects:
public List<Employee> Employees = new List<Employee>();
This list can only hold Employee objects, and when you get an object out of the list, it has the
Employee type instead of the less specific object type.
Lesson 16 also described the main advantages of generic classes: code reuse and specific type
checking. You can use the same generic
List<> class to hold a list of strings, doubles, or
Person objects. By requiring a specific data type, the class prevents you from accidentally adding
an
Employee object to a list of Order objects, and when you get an object from the list you know
it is an
Order.
In this lesson, you learn how to build your own generic classes so you can raise code reuse to a
whole new level.
Many other things can be generic. You can probably guess that you can build
generic structures because structures are so similar to classes. You can also
build generic methods (in either generic or non-generic classes), generic inter-
faces, generic delegate types, and so on. This lesson focuses on generic classes.
DEFINING GENERIC CLASSES
A generic class declaration looks a lot like a normal class declaration with one or more generic
type variables added in angled brackets. For example, the following code shows the basic dec-
laration for a generic
TreeNode class:
class TreeNode<T>
{
...
}
28
596906c28.indd 331 4/7/10 12:34:12 PM
332
LESSON 28 Making generic classes
The <T> means the class takes one type parameter, T. Within the class’s code, the type T means
whatever type the program used when creating the instance of the class. For example, the following
code declares a variable named
rootNode that is a TreeNode that handles strings:
TreeNode<string> rootNode = new TreeNode<string>();
If you want the class to use multiple type parameters, separate them with commas. For example,
suppose you want to make a Matcher class that takes two kinds of objects and matches objects in
the two kinds. It might match
Employee objects with Job objects to assign employees to jobs. The
following code shows how you might declare the
Matcher class:
public class Matcher<T1, T2>
{
...
}
The following code shows how you might create an instance of the class to match Employees
with
Jobs:
Matcher<Employee, Job> jobAssigner = new Matcher<Employee, Job>();
Many developers use T for name of the type in generic classes that take only
one type.
If the class takes more than one type, you should use more descriptive names so
its easy to tell the types apart. For example, the generic
Dictionary class has
two type variables named
TKey and TValue that represent the types of the keys
and values that the
Dictionary will hold.
Inside the class’s code, you can use the types freely. For example, the following code shows more of
the
TreeNode class’s code. A TreeNode object represents a node in a tree, with an associated piece
of data attached to it. The places where the class uses the data type
T are highlighted in bold.
class TreeNode<T>
{
// This node’s data.
public T Data { get; set; }
// This node’s children.
private List<TreeNode<T>> children = new List<TreeNode<T>>();
// Constructor.
public TreeNode(T data)
{
Data = data;
}
// Override ToString to display the data.
public override string ToString()
596906c28.indd 332 4/7/10 12:34:13 PM

Get Stephens' C# Programming with Visual Studio® 2010 24-Hour Trainer now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.