As famous as the word generics is among .Net developers, I was amazed when I found out that a huge percentage of .Net developers have only heard of it but have never actually used it or know of any reason why they should use it. If you have read my past articles, you would know that my philosophy is to code simple and efficiently, there is no need to write complex code that could have been done with simple techniques. Therefore, this article will be no different than any other, I'll briefly talk about generics and give simple examples and its uses.
Generics is only supported on the .Net 2.0+ frameworks and its really easy to understand and use. As the name implies generic - something that is not tied to anything, .Net Generics works in a similar manner. For example, if you buy a bottle of perfume with no brand name on it, you know you bought perfume and you know what to do with it but you really don't know what exact brand it is (if any) and that's how .Net Generics works. We can safely use a class in a type-safe manner without really knowing what specific type the class is. Lets take this scenario as an example, say we have class that has a list of products and a list of customers, we can create a single generic array/list class that can store them and at the end of the day, we will be able to access those objects as their actual type (products or customers) without boxing and un-boxing or casting. Be aware Generics can not be used in Web Services, Enterprise Services and Indigo.
Majority of the generic collection classes are maintained within the System.Collections.Generic namespace and the collections in these classes are used in the same way their predecessors were used. Version 1.1 or lower of the .Net Framework requires a developer to cast a class to an object before adding it to a collection which works fine, however, the object that is cast and added could be anything and the collection will not throw an exception - this method is prone to errors if someone adds a string instead of the expected int and you are trying to cast it to its original state while iterating through the items in the collection. Here is an example.
System.Collections.ArrayList
studentNames = new System.Collections.ArrayList();
// Although we know we want strings, the collections does not know that
// and no exception will be thrown if we add an invalid value
studentNames.Add("Rydal");
studentNames.Add("Jill");
studentNames.Add(89);
studentNames.Add("Jack");
studentNames.Add("Mary");
studentNames.Add(new Int32());
// When the interation gets to - '89' an error will be thrown
// because we are expection a string not an int value, and the same for the new Int32
foreach (string name in studentNames)
{
System.Console.Write(name);
}
I've seen several developers including myself create an additional type-safe collection class to hold a specific type of class/object, therefore, giving us a fair amount of type-safety, guaranteed type-safety I must say. However, its a pain on the fingers to manage and create a type-safe collection class for each class and that's were Generics comes in. Generics provides us a way to create a type-safe collection of items which can be use with any type possible. It would be ideal if we can create it once and never have to recreate it again. Here is an example of my generic class that can hold other type. Classes similar to this should be used to replace all of your type-safe collection classes.
/// <summary>
/// UseGenericClass
/// </summary>
/// <remarks>
/// Method that uses the GenericClass
/// </remarks>
///
private static void UseGenericClass()
{
GenericClass<string> genClass = new GenericClass<string>();
genClass.field = "String value";
System.Console.Write(genClass.field);
}
/// <summary>
/// GenericClass
/// </summary>
///
/// <typeparam name="T">Any type</typeparam>
/// <remarks>A generic class</remarks>
///
private class GenericClass<T>
{
public T field;
}
As you may have noticed above in the code, I specify what type it is (<string>) when instantiating the GenericClass and by doing so I established the new generic class (constructed generic class) as a string. <T> will be substituted with string all through out the class and the result is a type safe class tailored for your types.
Here are some snippets that converts our old type-safe collection way of doing things to generics using a Product class as an example.
/// <summary>
/// Product
/// </summary>
/// <remarks>
/// Our product class that represents a single product
/// </remarks>
///
public class Product
{
private string name = string.Empty;
private double price = 0.0;
private string sku = string.Empty;
public string Sku
{
get { return sku; }
set { sku = value; }
}
public double Price
{
get { return price; }
set { price = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
}
/// <summary>
/// UseGenericClass
/// </summary>
/// <remarks>
/// Method that uses the GenericClass
/// </remarks>
///
private static void UseGenericClass()
{
// Create the generic list
System.Collections.Generic.List<Product> products = new List<Product>();
// Populate the generic list with dummy products
// Note the clr is smart enough to know what to expect...look at intellisense
for (int i = 0; i <= 10; i++)
{
Product p = new Product();
p.Name = "ProductName" + i.ToString();
p.Price = 19.99d * double.Parse(i.ToString());
p.Sku = i.ToString();
products.Add(p); // We can only add products, otherwise it throws an error
}
// Iterate and print, no exceptions
foreach (Product p in products)
{
System.Console.WriteLine(p.Name);
}
}
This article is by no means complete, I had to make it short and to the point, its main goal is to introduce anyone with .Net coding experience to Generics. There is much more to learn about generics such as Generic Delegates, Interfaces, collections. I'll elaborate on upcoming articles.