views:

15056

answers:

12

Can anyone explain to me why I would want to use IList over List in C#?

Related question: Why is it considered bad to expose List<T>

+56  A: 

If you are exposing your class through a library that others will use, you generally want to expose it via interfaces rather than concrete implementations. This will help if you decide to change the implementation of your class later to use a different concrete class. In that case the user's of your library won't need to update their code since the interface doesn't change.

If you are just using it internally, you may not care so much, and using List<T> may be ok.

tvanfosson
I'm not understanding the (subtle) difference, is there some example you could point me to?
StingyJack
Say you had originally used List<T> and wanted to change to use a specialized CaseInsensitiveList<T>, both of which implement IList<T>. If you use the concrete type all callers need to be updated. If exposed as IList<T> the caller doesn't have to be changed.
tvanfosson
Ah. OK. I get that. Picking the lowest common denominator for a contract. Thanks!
StingyJack
This principle is an example of encapsulation, one of the three pillars of object-oriented programming. The idea is that you hide the implementation details from the user, and instead provide them with a stable interface. This is to reduce dependency on details that might change in the future.
Jason
Note also that T[] : IList<T>, so that for performance reasons you could always swap from returning a List<T> from your procedure to returning a T[], and if the procedure is declared to return IList<T> (or perhaps ICollection<T>, or IEnumerable<T>) nothing else would need to be changed.
Justice
Microsoft .NET 4.0 API is using List<T> instead of IList<T>... I wonder why? http://msdn.microsoft.com/en-us/library/system.web.caching.ioutputcacheentry_properties(VS.100).aspx
JarrettV
For performance reasons, you don't want to access `T[]` via its `IEnumerable<T>` interface, also arrays don't support e.g. `IList.Remove`
Ben Voigt
+10  A: 

IList<T> is an interface so you can inherit another class and still implement IList<T> while inheriting List<T> prevents you to do so.

For example if there is a class A and your class B inherits it then you can't use List<T>

class A : B, IList<T> { ... }
Diadistis
+2  A: 

You would because defining an IList or an ICollection would open up for other implementations of your interfaces.

You might wantet to have a IOrderRepository that defines a collection of orders in either a IList or ICollection, then you could have different kinds of implementations provide a list of orders as long as they conform to "rules" defined by your IList or ICollection.

Peter Lindholm
+10  A: 

A principle of TDD and OOP generally is programming to an interface not an implementation.

In this specific case since you're essentially talking about a language construct, not a custom one it generally won't matter, but say for example that you found List didn't support something you needed. If you had used IList in the rest of the app you could extend List with your own custom class and still be able to pass that around without refactoring.

The cost to do this is minimal, why not save yourself the headache later? It's what the interface principle is all about.

annakata
+3  A: 
public void Foo(IList<Bar> list)
{
     // Do Something with the list here.
}

In this case you could pass in any class which implements the IList<Bar> interface. If you used List<Bar> instead, only a List<Bar> instance could be passed in.

The IList<Bar> way is more loosely coupled than the List<Bar> way.

smack0007
+5  A: 

The most important case for using interfaces over implementations is in the parameters to your API. If your API takes a List parameter, then anyone who uses it has to use List. If the parameter type is IList, then the caller has much more freedom, and can use classes you never heard about, which may not even have existed when your code was written.

Michael Borgwardt
+11  A: 

List< T > is a specific implementation of IList< T >, which is a container that can be addressed the same way as a linear array T[] using an integer index. When you specify IList as the type of the method's argument, you only specify that you need certain capabilities of the container.

For example, the interface specification does not enforce a specific data structure to be used. The implementation of List< T > happens to the same performance for accessing, deleting and adding elements as a linear array. However, you could imagine an implementation that is backed by a linked list instead, for which adding elements to the end is cheaper (constant-time) but random-access much more expensive. (Note that the .NET LinkedList< T > does not implement IList< T >.)

This example also tells you that there may be situations when you need to specify the implementation, not the interface, in the argument list: In this example, whenever you require a particular access performance characteristic. This is usually guaranteed for a specific implementation of a container (List< T > documentation: "It implements the IList< T > generic interface using an array whose size is dynamically increased as required.").

Additionally, you might want to consider exposing the least functionality you need. For example. if you don't need to change the content of the list, you should probably consider using IEnumerable< T >, which IList< T> extends.

ILoveFortran
Regarding your last statement about using IEnumerable instead of IList. This is not always recommended, take WPF for example which will just create a wrapper IList object so will have an impact of perf - http://msdn.microsoft.com/en-us/library/bb613546.aspx
HAdes
Great answer, performance guarantees are something that an interface cannot deliver. In some code this can be quite important and using concrete classes communicates your intent, your need for that specific class. An interface on the other hand says "I just need to call this set of methods, no other contract implied."
joshperry
+30  A: 

Interface is a promise (or a contract).

As it is always with the promises - smaller the better.

Rinat Abdullin
Not always better, just easier to keep! :)
Kirk Broadhurst
What a great simple summary!
Cory House
+10  A: 

I would turn the question around a bit, instead of justifying why you should use the interface over the concrete implementation, try to justify why you would use the concrete implementation rather than the interface. If you can't justify it, use the interface.

Patrik Hägne
Very interesting way of thinking about it. And a good way to think when programming - thanks.
Peanut
Well said! Since the interface is the more flexible approach, you really should have to justify what the concrete implementation is buying you.
Cory House
+18  A: 
Arec Barrwin
That is so true.
scope_creep
I have to disagree with your sardonic answer. I don't totally disagree with the sentiment of over-architecture being a real problem. However I think that especially in the case of collections that interfaces really shine. Say I have a function that returns `IEnumerable<string>`, inside the function I may use a `List<string>` for an internal backing store to generate my collection, but I only want callers to enumerate it's contents, not add or remove. Accepting an interface as a parameter communicates a similar message "I need a collection of strings, don't worry though, I won't change it."
joshperry
Software development is all about translating intent. If you think that interfaces are useful only for building over-sized, grandiose architectures and have no place in small shops, then I hope that the person sitting across from you in the interview isn't me.
joshperry
The use of IList instead of List doesn't even introduce any additional words in the code, so I can hardly believe an argument that it leads to unnecessary code.
recursive
A: 
vishy
A: 

You can look at this argument from several angles including the one of a purely OO approach which says to program against an Interface not an implementation. With this thought, using IList follows the same principal as passing around and using Interfaces that you define from scratch. I also believe in the scalability and flexibility factors provided by an Interface in general. If a class implmenting IList<T> needs to be extended or changed, the consuming code does not have to change; it knows what the IList Interface contract adheres to. However using a concrete implementation and List<T> on a class that changes, could cause the calling code to need to be changed as well. This is because a class adhering to IList<T> guarantees a certain behavior that is not guaranteed by a concrete type using List<T>.

Also having the power to do something like modify the default implementation of List<T> on a class Implementing IList<T> for say the .Add, .Remove or any other IList method gives the developer a lot of flexibility and power, otherwise predefined by List<T>

atconway