Wednesday, May 19, 2010

Using Extension methods on Lists to make it fluent

Since C# 3.0 you can write extension methods on any class that you want, even if you don’t have the source code of the class. In other words you can extend a class with your own methods.

Extension methods can only be declared in static classes as static methods.

Extensions on List<T> classes can be very handy and make your code more readable and fluent.
Suppose you have this mixed Animal list with Dogs and Cats from this blogpost.

List<Animal> animalList = new List<Animal>(); 
animalList.Add(new Dog("Dog1", ConsoleColor.Red));
animalList.Add(new Dog("Dog2", ConsoleColor.Green));
animalList.Add(new Dog("Dog3", ConsoleColor.Red));
animalList.Add(new Cat("Cat1", ConsoleColor.Black));
animalList.Add(new Cat("Cat2", ConsoleColor.Black));
animalList.Add(new Cat("Cat3", ConsoleColor.Black));

(Never mind the ConsoleColor for the animal ;-) )

Suppose we want all the red dogs from the animalList, we could write our code like:

//Get the Red docs

List<Dog> redDogList = animalList.OfType<Dog>().Where(n => n.Color == ConsoleColor.Red).ToList();

This works, however everytime we want to get some colored animal we would get the same type of code. We would probably write some static methods to avoid this :

 List<Dog> redDogList = ListUtils.GetTheDogs(animalList);

Even better is to make this static extension methods so that the functionality looks to be encapsulated by the list its self. We can then also make the method names more readable, for instant not “GetTheDog”, but “WhichAreDog”.

For example:
public static List<Animal> WhichAreDog(this List<Animal> animalList)
  return animalList.OfType<Dog>().Cast<Animal>().ToList();

public static
List<Animal> HavingColor(this List<Animal> animalList, ConsoleColor color)
  return animalList.Where(n => n.Color == color).ToList();

The “this” before the first parameter of the method indicates that this is an extension method on this parameter, in this case the list with animals.

Now getting the red dogs looks like this:

List<Animal> allRedDogs = 

Much more readable and fluent!


Kyle A. Miller said...

Delphi Prism does this better.

Roland Beenhakker said...

@Kyle A. Miller In what way do you find it better? Syntax?