“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
Let’s take a look at the following code as an example:
[Test]
public void GetStudents_ShouldReturnAllStudents()
{
List<Student> students = _store.GetStudents();
Assert.IsNotNull(students);
foreach (Student student in students)
{
Console.WriteLine(student.FirstName + student.LastName);
}
}
The code above is tightly bound to a specialized type of collection, List<T>.
If we crack open Lutz Reflector and take a look at the List<T> type we can see that it implements IList<T> and ICollection<T>.

If we wanted to code to an abstraction, in this case we have two options, IList<T>, ICollection<T>.
(For the above test it would probably be best to use IEnumerable<T>, but let’s assume we need to add items to the collection in client code.)
If we take a look at IList<T>…

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

The final code looks more like this:
[Test]
public void GetStudents_ShouldReturnAllStudents()
{
ICollection<Student> students = _store.GetStudents();
Assert.IsNotNull(students);
foreach(Student student in students)
{
Console.WriteLine(student.FirstName + student.LastName);
}
}
As a side note, for this particular contrived example since ICollection<T> also implements IEnumerable<T> the above can be re-written as follows
(without any changes to the implementation of GetStudents())
[Test]
public void GetStudents_ShouldReturnAllStudents()
{
IEnumerable <Student> students = _store.GetStudents();
Assert.IsNotNull(students);
foreach(Student student in students)
{
Console.WriteLine(student.FirstName + student.LastName);
}
}