“By using the interface, I allow myself the advantage of making it easier to change implementations later on if I need to. Another implementation may provide performance improvements, some database interaction features, or other benefits. By programming to the interface rather than to the implementation, I avoid having to change all the code should I need a different implementation… You should always try to program to an interface like this; always use the most general type you can.” - Martin Fowler - UML Distilled: A Brief Guide to the Standard Object Modeling Language, Third Edition by Martin Fowler

Read more about this title…

Let’s take a look at the following code as an example:

 1 [Test]
 2   public void GetStudents_ShouldReturnAllStudents( ) 
 3   {
 4     List< Student > students = _store.GetStudents( );
 5     Assert.IsNotNull( students );
 6     foreach ( Student student in students ) 
 7     {
 8       Console.WriteLine( student.FirstName + student.LastName );
 9     }
10   }

The code above is tightly bound to a specialized type of collection, List. If we crack open Lutz Reflector and take a look at the List type we can see that it implements IList and ICollection.

If we wanted to code to an abstraction, in this case we have two options, IList, ICollection. (For the above test it would probably be best to use IEnumerable, but let's assume we need to add items to the collection in client code.)

If we take a look at IList...

As you can see IList implements ICollection. ICollection does not implement IList, it would be safe to say that ICollection is the most generalized form of List or IList, which gives us the greatest flexibility to change the underlying implementation of "GetStudents()" in the future.

The final code looks more like this:

 1 [Test]
 2   public void GetStudents_ShouldReturnAllStudents( ) 
 3   {
 4     ICollection< Student > students = _store.GetStudents( );
 5     Assert.IsNotNull( students );
 6     foreach( Student student in students ) 
 7     {
 8       Console.WriteLine( student.FirstName + student.LastName );
 9     }
10   }

As a side note, for this particular contrived example since ICollection also implements IEnumerable the above can be re-written as follows (without any changes to the implementation of GetStudents())

 1 [Test]
 2   public void GetStudents_ShouldReturnAllStudents( ) 
 3   {
 4     IEnumerable < Student > students = _store.GetStudents( );
 5     Assert.IsNotNull( students );
 6     foreach( Student student in students ) 
 7     {
 8       Console.WriteLine( student.FirstName + student.LastName );
 9     }
10   }

Additional Resources: * C# Interface Based Development * The Interface Construct in C#

comments powered by Disqus