C# generics are one of the greatest features of c# in my opinion. They are so great because they give you:
Type Safe Collections
In the old arraylist, you had code like this:
ArrayList a = new ArrayList();
a.Add(new object());
a.Add(new Foo());
a.Add(1);
if you then did code to iterate through the list, you would need to add tons of code to determine the type. If you didn’t, you could easily get run-time errors trying to cast to the wrong type.
foreach(object o in a)
{
if(object.GetType() == Foo.GetType())
{
Foo myFoo = (Foo)object;
}
}
This is a major pain. Putting the wrong type of object in your ArrayList leads to run-time errors not detected at compile time.
But now with Generics, you use the following code:
List<int> l = new List<int>();
l.add(1);
l.add(2);
and if you try and add an object that is not an int, it won’t compile!
l.add(new Foo); // throws compilation error.
Collections Without Boxing and Unboxing
In the old ArrayList, you’d have a list like this:
ArrayList a = new ArrayList();
a.Add(1);
a.Add(2);
a.Add(3);
But the arraylist is storing these ints as type object. To add them to the arraylist, the CLR has to box (create a reference type wrapper around a value type) the int since it is a value type, which is very expensive!
In addition, the CLR has to unbox (convert from reference type value type wrapper to the real value type) the object in the arraylist when you take it out, which is also very expensive. I read somewhere on MSDN it’s literally 2 to 3 times slower. That’s a huge difference! For instance:
foreach(object o in a)
{
// this incurs unboxing performance penalties
int myInt = (int)o;
}
With generics, all you do is this:
List<int> l = new List<int>();
l.Add(1);
l.Add(2);
l.Add(3);
foreach(int i in l)
{
// it’s already an int - no unboxing needed here! much improved performance!
}
Collections Without Casting
When you want to access an element in the arraylist, the cast to get the real type out of the object is expensive. For instance:
foreach(object o in a)
{
// performance hit from the CAST also
int myInt = (int)o;
}
With generics, all you do is this:
List<int> l = new List<int>();
l.Add(1);
l.Add(2);
l.Add(3);
foreach(int i in l)
{
// it’s already an int - no casting needed here! much improved performance!
}
Creating generic algorithms with pluggable types
A new trick I learned with generics is that you can add generic types to instance or static methods.
So if you define a method as
public List<T> RemoveUnwantedTypes<U>(List<T>)
{
foreach(T genericTypeInstance in List<T>)
{
if(genericTypeInstance is U)
{
list.Remove(genericTypeInstance);
}
}
}
To use this to filter a list to remove types you did not want, you would type:
List<BaseClass> list = new List<BaseClass>();
// For this to work, both MyClass and FooBar have to inherit from BaseClass.
// So we are using polymorphism here as well.
list.Add(new MyClass());
list.Add(new FooBar()):
List<BaseClass> filteredList = RemoveUnwantedTypes<FooBar>(list);
Now you would end up with a list of 1 element, which only contained the class MyClass() instance in it. You can do so much with this concept!
Click Here To Share This With Other Popular Social Sites