Home > Articles > Programming > Windows Programming

  • Print
  • + Share This
This chapter is from the book

Generics

“Generics are classes, structures, interfaces, and methods that have placeholders for one or more of the types they store or use” (Microsoft 2006). Here is an example of a generic class introduced in the System.Collections.Generic namespace of the .NET Framework 2.0 Class Library:

public class List<T>

Among the methods of that class is this one:

public Add(T item)

Here, T is the placeholder for the type that an instance of the generic class System.Collections.Generic.List<T> will store. In defining an instance of the generic class, one specifies the actual type that the instance will store:

List<string> myListOfStrings = new List<string>();

Then one can use the Add() method of the generic class instance like so:

myListOfStrings.Add("Hello, World");

Evidently, generics enabled the designer of the List<T> class to define a collection of instances of the same unspecified type; in other words, to provide the template for a type-safe collection. A user of List<T> can employ it to contain instances of a type of the user’s choosing, without the designer of List<T> having to know which type the user might choose. Note as well that whereas a type that is derived from a base type is meant to derive some of the functionality it requires from the base, with the remainder still having to be programmed, List<string> comes fully equipped from List<T>.

The class, System.Collections.Generic.List<T>, is referred to as a generic type definition. The placeholder, T, is referred to as a generic type parameter. Declaring

List<string> myListOfStrings;

yields System.Collections.Generic.List<string> as a constructed type, and string as a generic type argument.

Generics can have any number of generic type parameters. For example, System.Collections.Generic.Dictionary<TKey, TValue> has two.

The designer of a generic may use constraints to restrict the types that can be used as generic type arguments. This generic type definition

public class MyGenericType<T> where T: new(), IComparable

constrains the generic type arguments to types with a public, parameter-less constructor that implements the IComparable interface. This less restrictive generic type definition

public class MyGenericType<T> where T: class

merely constrains generic type arguments to reference types.

Both generic and nongeneric types can have generic methods. Here is an example of a nongeneric type with a generic method:

using System;

public class Printer
{
    public void Print<T>(T   argument)
    {
        Console.WriteLine(argument.ToString());
    }

    static void Main(string[] arguments)
    {
        Printer printer = new Printer();
        printer.Print<string>("Hello, World");
        Console.WriteLine("Done");
        Console.ReadKey();
    }
}

In programming a generic, it is often necessary to determine the type of generic argument that has been substituted for a generic type parameter. This revision to the preceding example shows how one can make that determination:

public class Printer
{
    public void Print<T>(T argument)
    {
        if(typeof(T) == typeof(string))
        {
            Console.WriteLine(argument);
        }
        else
        {
            Console.WriteLine(argument.ToString());
        }
    }

    static void Main(string[] arguments)
    {
        Printer printer = new Printer();
        printer.Print<string>("Hello, World");
        Console.WriteLine("Done");
        Console.ReadKey();
    }
}

A generic interface may be implemented by a generic type or a nongeneric type. Also, both generic and nongeneric types may inherit from generic base types.

public interface IMyGenericInterface<T>
{
    void MyMethod<T>();
}

public class MyGenericImplementation<T>: IMyGenericInterface<T>
{
    public void MyMethod<T>()
    {
    }
}

public class MyGenericDescendant<T> : MyGenericImplementation<T>
{
}

public class MyNonGenericImplementation : IMyGenericInterface<string>
{
    public void MyMethod<T>()
    {
    }
}

public class MyNonGenericDescendant : MyGenericImplementation<string>
{
}
  • + Share This
  • 🔖 Save To Your Account