In a nutshell, you should **define an interface when you need the ability to swap out an implementation defined by that interface.**  

What does that phrase mean?

As an example, if you're unit testing and need to substitute a stub or mock for a constructor parameter, then that constructor parameter should be defined as an interface so that you can pass an object that appropriately "simulates" the correct behavior.  

This is also the basis for the Dependency Inversion principle; instead of a class taking concrete dependencies on other classes and instantiating them directly (thereby creating tight coupling), the class implements dependencies by allowing conforming objects to be passed into the constructor via interfaces.

In your `List` example, it's not a given that you need access to the List's entire set of capabilities.  If you simply need to iterate over the list, it is sufficient to pass the list as an `IEnumerable`, and you're exercising the Liskov Substitution Principle by doing so.  You don't have to couple yourself to the entire `List` class.