Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
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>
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 users 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.
The less popular answer is programmers like to pretend their software is going to be re-used the world over, when infact the majority of projects will be maintained by a small amount of people and however nice interface-related soundbites are, you're deluding yourself.
Architecture Astronauts. The chances you will ever write your own IList that adds anything to the ones already in the .NET framework are so remote that it's theoretical jelly tots reserved for "best practices".
Obviously if you are being asked which you use in an interview, you say IList, smile, and both look pleased at yourselves for being so clever. Or for a public facing API, IList. Hopefully you get my point.
Interface is a promise (or a contract).
As it is always with the promises - smaller the better.
Some people say "always use IList<T> instead of List<T>".
They want you to change your method signatures from void Foo(List<T> input) to void Foo(IList<T> input).
These people are wrong.
It's more nuanced than that. If you are returning an IList<T> as part of the public interface to your library, you leave yourself interesting options to perhaps make a custom list in the future. You may not ever need that option, but it's an argument. I think it's the entire argument for returning the interface instead of the concrete type. It's worth mentioning, but in this case it has a serious flaw.
As a minor counterargument, you may find every single caller needs a List<T> anyway, and the calling code is littered with .ToList()
But far more importantly, if you are accepting an IList as a parameter you'd better be careful, because IList<T> and List<T> do not behave the same way. Despite the similarity in name, and despite sharing an interface they do not expose the same contract.
Suppose you have this method:
public Foo(List<int> a)
{
a.Add(someNumber);
}
A helpful colleague "refactors" the method to accept IList<int>.
Your code is now broken, because int[] implements IList<int>, but is of fixed size. The contract for ICollection<T> (the base of IList<T>) requires the code that uses it to check the IsReadOnly flag before attempting to add or remove items from the collection. The contract for List<T> does not.
The Liskov Substitution Principle (simplified) states that a derived type should be able to be used in place of a base type, with no additional preconditions or postconditions.
This feels like it breaks the Liskov substitution principle.
int[] array = new[] {1, 2, 3};
IList<int> ilist = array;
ilist.Add(4); // throws System.NotSupportedException
ilist.Insert(0, 0); // throws System.NotSupportedException
ilist.Remove(3); // throws System.NotSupportedException
ilist.RemoveAt(0); // throws System.NotSupportedException
But it doesn't. The answer to this is that the example used IList<T>/ICollection<T> wrong. If you use an ICollection<T> you need to check the IsReadOnly flag.
if (!ilist.IsReadOnly)
{
ilist.Add(4);
ilist.Insert(0, 0);
ilist.Remove(3);
ilist.RemoveAt(0);
}
else
{
// what were you planning to do if you were given a read only list anyway?
}
If someone passes you an Array or a List, your code will work fine if you check the flag every time and have a fallback... But really; who does that? Don't you know in advance if your method needs a list that can take additional members; don't you specify that in the method signature? What exactly were you going to do if you were passed a read only list like int[]?
You can substitute a List<T> into code that uses IList<T>/ICollection<T> correctly. You cannot guarantee that you can substitute an IList<T>/ICollection<T> into code that uses List<T>.
There's an appeal to the Single Responsibility Principle / Interface Segregation Principle in a lot of the arguments to use abstractions instead of concrete types - depend on the narrowest possible interface. In most cases, if you are using a List<T> and you think you could use a narrower interface instead - why not IEnumerable<T>? This is often a better fit if you don't need to add items. If you need to add to the collection, use the concrete type, List<T>.
For me IList<T> (and ICollection<T>) is the worst part of the .NET framework. IsReadOnly violates the principle of least surprise. A class, such as Array, which never allows adding, inserting or removing items should not implement an interface with Add, Insert and Remove methods. (see also https://softwareengineering.stackexchange.com/questions/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties)
Is IList<T> a good fit for your organisation? If a colleague asks you to change a method signature to use IList<T> instead of List<T>, ask them how they'd add an element to an IList<T>. If they don't know about IsReadOnly (and most people don't), then don't use IList<T>. Ever.
Note that the IsReadOnly flag comes from ICollection<T>, and indicates whether items can be added or removed from the collection; but just to really confuse things, it does not indicate whether they can be replaced, which in the case of Arrays (which return IsReadOnlys == true) can be.
For more on IsReadOnly, see msdn definition of ICollection<T>.IsReadOnly
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<T> 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.
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.
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> { ... }
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.
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.
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.
Supprising that none of these List vs IList questions (or answers) mentions the signature difference. (Which is why I searched for this question on SO!)
So here's the methods contained by List that are not found in IList, at least as of .NET 4.5 (circa 2015)
AddRange
AsReadOnly
BinarySearch
Capacity
ConvertAll
Exists
Find
FindAll
FindIndex
FindLast
FindLastIndex
ForEach
GetRange
InsertRange
LastIndexOf
RemoveAll
RemoveRange
Reverse
Sort
ToArray
TrimExcess
TrueForAll
What if .NET 5.0 replaces System.Collections.Generic.List<T> to System.Collection.Generics.LinearList<T>. .NET always owns the name List<T> but they guarantee that IList<T> is a contract. So IMHO we (atleast I) are not supposed to use someone's name (though it is .NET in this case) and get into trouble later.
In case of using IList<T>, the caller is always guareented things to work, and the implementer is free to change the underlying collection to any alternative concrete implementation of IList
All concepts are basically stated in most of the answers above regarding why use interface over concrete implementations.
IList<T> defines those methods (not including extension methods)
IList<T> MSDN link
Add
Clear
Contains
CopyTo
GetEnumerator
IndexOf
Insert
Remove
RemoveAt
List<T> implements those nine methods (not including extension methods), on top of that it has about 41 public methods, which weighs in your consideration of which one to use in your application.
List<T> MSDN link
You would because defining an IList or an ICollection would open up for other implementations of your interfaces.
You might want to have an IOrderRepository that defines a collection of orders in either a IList or ICollection. You could then have different kinds of implementations to provide a list of orders as long as they conform to "rules" defined by your IList or ICollection.
IList<> is almost always preferable as per the other poster's advice, however note there is a bug in .NET 3.5 sp 1 when running an IList<> through more than one cycle of serialization / deserialization with the WCF DataContractSerializer.
There is now a SP to fix this bug : KB 971030
The interface ensures that you at least get the methods you are expecting; being aware of the definition of the interface ie. all abstract methods that are there to be implemented by any class inheriting the interface. so if some one makes a huge class of his own with several methods besides the ones he inherited from the interface for some addition functionality, and those are of no use to you, its better to use a reference to a subclass (in this case the interface) and assign the concrete class object to it.
additional advantage is that your code is safe from any changes to concrete class as you are subscribing to only few of the methods of concrete class and those are the ones that are going to be there as long as the concrete class inherits from the interface you are using. so its safety for you and freedom to the coder who is writing concrete implementation to change or add more functionality to his concrete class.
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>
Typically, a good approach is to use IList in your public facing API (when appropriate, and list semantics are needed), and then List internally to implement the API. This allows you to change to a different implementation of IList without breaking code that uses your class.
The class name List may be changed in next .net framework but the interface is never going to change as interface is contract.
Note that, if your API is only going to be used in foreach loops, etc, then you might want to consider just exposing IEnumerable instead.
Related
The answers to questions like this: List<T> or IList<T> always seem to agree that returning an interface is better than returning a concrete implementation of a collection. But I'm struggling with this. Instantiating an interface is impossible, so if your method is returning an interface, it's actually still returning a specific implementation. I was experimenting a bit with this by writing 2 small methods:
public static IList<int> ExposeArrayIList()
{
return new[] { 1, 2, 3 };
}
public static IList<int> ExposeListIList()
{
return new List<int> { 1, 2, 3 };
}
And use them in my test program:
static void Main(string[] args)
{
IList<int> arrayIList = ExposeArrayIList();
IList<int> listIList = ExposeListIList();
//Will give a runtime error
arrayIList.Add(10);
//Runs perfectly
listIList.Add(10);
}
In both cases when I try to add a new value, my compiler gives me no errors, but obviously the method which exposes my array as an IList<T> gives a runtime error when I try to add something to it.
So people who don't know what's happening in my method, and have to add values to it, are forced to first copy my IList to a List to be able to add values without risking errors. Of course they can do a typecheck to see if they're dealing with a List or an Array, but if they don't do that, and they want to add items to the collection they have no other choice to copy the IList to a List, even if it already is a List. Should an array never be exposed as IList?
Another concern of mine is based upon the accepted answer of the linked question (emphasis mine):
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 users 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 may be ok.
Imagine someone actually used my IList<T> they got from my ExposeListIlist() method just like that to add/remove values. Everything works fine. But now like the answer suggests, because returning an interface is more flexible I return an array instead of a List (no problem on my side!), then they're in for a treat...
TLDR:
1) Exposing an interface causes unnecessary casts? Does that not matter?
2) Sometimes if users of the library don't use a cast, their code can break when you change your method, even though the method remains perfectly fine.
I am probably overthinking this, but I don't get the general consensus that returning an interface is to be preferred over returning an implementation.
Maybe this is not directly answering your question, but in .NET 4.5+, I prefer to follow these rules when designing public or protected APIs:
do return IEnumerable<T>, if only enumeration is available;
do return IReadOnlyCollection<T> if both enumeration and items count are available;
do return IReadOnlyList<T>, if enumeration, items count and indexed access are available;
do return ICollection<T> if enumeration, items count and modification are available;
do return IList<T>, if enumeration, items count, indexed access and modification are available.
Last two options assume, that method must not return array as IList<T> implementation.
No, because the consumer should know what exactly IList is:
IList is a descendant of the ICollection interface and is the base
interface of all non-generic lists. IList implementations fall into
three categories: read-only, fixed-size, and variable-size. A
read-only IList cannot be modified. A fixed-size IList does not allow
the addition or removal of elements, but it allows the modification of
existing elements. A variable-size IList allows the addition, removal,
and modification of elements.
You can check for IList.IsFixedSize and IList.IsReadOnly and do what you want with it.
I think IList is an example of a fat interface and it should have been split into multiple smaller interfaces and it also violates Liskov substitution principle when you return an array as an IList.
Read more if you want to make decision about returning interface
UPDATE
Digging more and I found that IList<T> does not implement IList and IsReadOnly is accessible through base interface ICollection<T> but there is no IsFixedSize for IList<T>. Read more about why generic IList<> does not inherit non-generic IList?
As with all "interface versus implementation" question, you'll have to realise what exposing a public member means: it defines the public API of this class.
If you expose a List<T> as a member (field, property, method, ...), you tell the consumer of that member: the type obtained by accessing this method is a List<T>, or something derived of that.
Now if you expose an interface, you hide the "implementation detail" of your class using a concrete type. Of course you can't instantiate IList<T>, but you can use an Collection<T>, List<T>, derivations thereof or your own type implementing IList<T>.
The actual question is "Why does Array implement IList<T>", or "Why has the IList<T> interface so many members".
It also depends on what you want the consumers of that member to do. If you actually return an internal member through your Expose... member, you'll want to return a new List<T>(internalMember) anyway, as otherwise the consumer can try and cast them to IList<T> and modify your internal member through that.
If you just expect consumers to iterate the results, expose IEnumerable<T> or IReadOnlyCollection<T> instead.
Be careful with blanket quotes that are taken out of context.
Returning an interface is better than returning a concrete implementation
This quote only makes sense if it's used in the context of the SOLID principles. There are 5 principles but for the purposes of this discussion we'll just talk about the last 3.
Dependency inversion principle
one should “Depend upon Abstractions. Do not depend upon concretions.”
In my opinion, this principle is the most difficult to understand. But if you look at the quote carefully it looks a lot like your original quote.
Depend on interfaces (abstractions). Do no depend on concrete implementations (concretions).
This is still a little confusing but if we start applying the other principles together it starts to make a lot more sense.
Liskov substitution principle
“objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.”
As you pointed out, returning an Array is clearly different behavior to returning a List<T> even though they both implement IList<T>. This is most certainly a violation of LSP.
The important thing to realize is that interfaces are about the consumer. If you're returning an interface, you've created a contract that any methods or properties on that interface can be used without changing the behavior of the program.
Interface segregation principle
“many client-specific interfaces are better than one general-purpose interface.”
If you're returning an interface, you should return the most client specific interface your implementation supports. In other words, if you're not expecting the client to call the Add method you shouldn't return an interface with an Add method on it.
Unfortunately, the interfaces in the .NET framework (particularly the early versions) are not always ideal client specific interfaces. Although as #Dennis pointed out in his answer, there are a lot more choices in .NET 4.5+.
Returning an interface is not necessarily better than returning a concrete implementation of a collection. You should always have a good reason to use an interface instead of a concrete type. In your example it seems pointless to do so.
Valid reasons to use an interface could be:
You do not know what the implementation of the methods returning the interface will look like and there may be many, developed over time. It may be other people writing them, from other companies. So you just want to agree on the bare necessities and leave it up to them how to implement the functionality.
You want to expose some common functionality independent from your class hierarchy in a type-safe way. Objects of different base types that should offer the same methods would implement your interface.
One could argue that 1 and 2 are basically the same reason. They are two different scenarios that ultimately lead to the same need.
"It's a contract". If the contract is with yourself and your application is closed in both functionality and time, there is often no point in using an interface.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
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>
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 users 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.
The less popular answer is programmers like to pretend their software is going to be re-used the world over, when infact the majority of projects will be maintained by a small amount of people and however nice interface-related soundbites are, you're deluding yourself.
Architecture Astronauts. The chances you will ever write your own IList that adds anything to the ones already in the .NET framework are so remote that it's theoretical jelly tots reserved for "best practices".
Obviously if you are being asked which you use in an interview, you say IList, smile, and both look pleased at yourselves for being so clever. Or for a public facing API, IList. Hopefully you get my point.
Interface is a promise (or a contract).
As it is always with the promises - smaller the better.
Some people say "always use IList<T> instead of List<T>".
They want you to change your method signatures from void Foo(List<T> input) to void Foo(IList<T> input).
These people are wrong.
It's more nuanced than that. If you are returning an IList<T> as part of the public interface to your library, you leave yourself interesting options to perhaps make a custom list in the future. You may not ever need that option, but it's an argument. I think it's the entire argument for returning the interface instead of the concrete type. It's worth mentioning, but in this case it has a serious flaw.
As a minor counterargument, you may find every single caller needs a List<T> anyway, and the calling code is littered with .ToList()
But far more importantly, if you are accepting an IList as a parameter you'd better be careful, because IList<T> and List<T> do not behave the same way. Despite the similarity in name, and despite sharing an interface they do not expose the same contract.
Suppose you have this method:
public Foo(List<int> a)
{
a.Add(someNumber);
}
A helpful colleague "refactors" the method to accept IList<int>.
Your code is now broken, because int[] implements IList<int>, but is of fixed size. The contract for ICollection<T> (the base of IList<T>) requires the code that uses it to check the IsReadOnly flag before attempting to add or remove items from the collection. The contract for List<T> does not.
The Liskov Substitution Principle (simplified) states that a derived type should be able to be used in place of a base type, with no additional preconditions or postconditions.
This feels like it breaks the Liskov substitution principle.
int[] array = new[] {1, 2, 3};
IList<int> ilist = array;
ilist.Add(4); // throws System.NotSupportedException
ilist.Insert(0, 0); // throws System.NotSupportedException
ilist.Remove(3); // throws System.NotSupportedException
ilist.RemoveAt(0); // throws System.NotSupportedException
But it doesn't. The answer to this is that the example used IList<T>/ICollection<T> wrong. If you use an ICollection<T> you need to check the IsReadOnly flag.
if (!ilist.IsReadOnly)
{
ilist.Add(4);
ilist.Insert(0, 0);
ilist.Remove(3);
ilist.RemoveAt(0);
}
else
{
// what were you planning to do if you were given a read only list anyway?
}
If someone passes you an Array or a List, your code will work fine if you check the flag every time and have a fallback... But really; who does that? Don't you know in advance if your method needs a list that can take additional members; don't you specify that in the method signature? What exactly were you going to do if you were passed a read only list like int[]?
You can substitute a List<T> into code that uses IList<T>/ICollection<T> correctly. You cannot guarantee that you can substitute an IList<T>/ICollection<T> into code that uses List<T>.
There's an appeal to the Single Responsibility Principle / Interface Segregation Principle in a lot of the arguments to use abstractions instead of concrete types - depend on the narrowest possible interface. In most cases, if you are using a List<T> and you think you could use a narrower interface instead - why not IEnumerable<T>? This is often a better fit if you don't need to add items. If you need to add to the collection, use the concrete type, List<T>.
For me IList<T> (and ICollection<T>) is the worst part of the .NET framework. IsReadOnly violates the principle of least surprise. A class, such as Array, which never allows adding, inserting or removing items should not implement an interface with Add, Insert and Remove methods. (see also https://softwareengineering.stackexchange.com/questions/306105/implementing-an-interface-when-you-dont-need-one-of-the-properties)
Is IList<T> a good fit for your organisation? If a colleague asks you to change a method signature to use IList<T> instead of List<T>, ask them how they'd add an element to an IList<T>. If they don't know about IsReadOnly (and most people don't), then don't use IList<T>. Ever.
Note that the IsReadOnly flag comes from ICollection<T>, and indicates whether items can be added or removed from the collection; but just to really confuse things, it does not indicate whether they can be replaced, which in the case of Arrays (which return IsReadOnlys == true) can be.
For more on IsReadOnly, see msdn definition of ICollection<T>.IsReadOnly
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<T> 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.
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.
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> { ... }
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.
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.
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.
Supprising that none of these List vs IList questions (or answers) mentions the signature difference. (Which is why I searched for this question on SO!)
So here's the methods contained by List that are not found in IList, at least as of .NET 4.5 (circa 2015)
AddRange
AsReadOnly
BinarySearch
Capacity
ConvertAll
Exists
Find
FindAll
FindIndex
FindLast
FindLastIndex
ForEach
GetRange
InsertRange
LastIndexOf
RemoveAll
RemoveRange
Reverse
Sort
ToArray
TrimExcess
TrueForAll
What if .NET 5.0 replaces System.Collections.Generic.List<T> to System.Collection.Generics.LinearList<T>. .NET always owns the name List<T> but they guarantee that IList<T> is a contract. So IMHO we (atleast I) are not supposed to use someone's name (though it is .NET in this case) and get into trouble later.
In case of using IList<T>, the caller is always guareented things to work, and the implementer is free to change the underlying collection to any alternative concrete implementation of IList
All concepts are basically stated in most of the answers above regarding why use interface over concrete implementations.
IList<T> defines those methods (not including extension methods)
IList<T> MSDN link
Add
Clear
Contains
CopyTo
GetEnumerator
IndexOf
Insert
Remove
RemoveAt
List<T> implements those nine methods (not including extension methods), on top of that it has about 41 public methods, which weighs in your consideration of which one to use in your application.
List<T> MSDN link
You would because defining an IList or an ICollection would open up for other implementations of your interfaces.
You might want to have an IOrderRepository that defines a collection of orders in either a IList or ICollection. You could then have different kinds of implementations to provide a list of orders as long as they conform to "rules" defined by your IList or ICollection.
IList<> is almost always preferable as per the other poster's advice, however note there is a bug in .NET 3.5 sp 1 when running an IList<> through more than one cycle of serialization / deserialization with the WCF DataContractSerializer.
There is now a SP to fix this bug : KB 971030
The interface ensures that you at least get the methods you are expecting; being aware of the definition of the interface ie. all abstract methods that are there to be implemented by any class inheriting the interface. so if some one makes a huge class of his own with several methods besides the ones he inherited from the interface for some addition functionality, and those are of no use to you, its better to use a reference to a subclass (in this case the interface) and assign the concrete class object to it.
additional advantage is that your code is safe from any changes to concrete class as you are subscribing to only few of the methods of concrete class and those are the ones that are going to be there as long as the concrete class inherits from the interface you are using. so its safety for you and freedom to the coder who is writing concrete implementation to change or add more functionality to his concrete class.
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>
Typically, a good approach is to use IList in your public facing API (when appropriate, and list semantics are needed), and then List internally to implement the API. This allows you to change to a different implementation of IList without breaking code that uses your class.
The class name List may be changed in next .net framework but the interface is never going to change as interface is contract.
Note that, if your API is only going to be used in foreach loops, etc, then you might want to consider just exposing IEnumerable instead.
I have been hearing that it is important to use the lowest class possible when passing parameters to methods. Why is this? Also where can i find more information on what the class hierarchy is? I would like to know what IEnumerable inheriated from and so forth.
If you use IEnumerable<T> as a parameter type, then you can pass in any type that implements that interface. That includes List<T>, Stack<T>, Queue<T>, etc.
It also includes various anonymous types that might be the result of a LINQ query, and also the very important IQueryable<T>.
By using "low-level" arguments, you give your method the ability to work on a larger variety of objects. It encourages writing generic re-usable methods.
MSDN can tell you what different things inherit from (in the case of IEnumerable, it inherits from nothing, because it represents pretty much the most primitive idea of a "list")
IEnumerable is a read-only sequence, while a List can be appended to.
If you design your public API so that it exposes IList<T> all over the place and then realize that you want to return a read only list, you have to either break your code by changing to IEnumerable<T> or use the horrible ReadOnlyCollection. I call it horrible because it throws exceptions on .Add/.Remove etc.
So if you only need to read, return IEnumerable, if your callers need to add/append, return IList.
On another note: Never return a List<T>, always an IList<T>. The reason is that List is a concrete class that can't be overridden in any sensible way, while IList is an interface that allows you to change the actual implementation without breaking the public contract.
The quickest thing I can think of is this: what happens if you no longer want your implementation to be of type List<T>?
Let's say you one day decide to refactor your application to use a LinkedList<T> or a SortedList<T>, all you have to change is that type instead of all of the types in all of the methods you might be passing your collection around to.
You can improve the maintainability of your code by using this technique.
The idea is to maximize the flexibility of your function. If you require a List<T>, then callers must have one to pass in. If they don't have one handy, they'll have to create one, and this is expensive. If you require IEnumerable<T>, on the other hand, then they can pass in any collection.
The best place to fnd information on the class heiarchy in .NET is MSDN.
To use such great function as ConvertAll(), I have to convert IList to List, it's painful.
Note that List<> is an implementation of IList<> with actual storage, i.e. it holds an array in the background. In general, an IList<> can be a proxy to something else. In db4o and linq to sql, your IList<> could 'point to a query', i.e. accessing the list will trigger a database operation.
This way, you can perform myList.Skip(600).Take(20); to perform pagination and only in this step will the actual query be executed. A List<> containing a million entries will be huge, while there may be IList<>s that have a huge Count, but don't eat a significant amount of memory - as long as you don't access the elements.
ConvertAll will require each and every object be instantiated so it is a costly operation. Thus, it is better to make the operation explicit and force you to retrieve a specific implementation of the interface. Obviously, conversion requires all objects to be instantiated anyway, so there's no benefit in doing it lazily.
Why don't use IEnumerable<T>.Select instead of List<T>.ConvertAll? Since IList inherits IEnumerable. See this question on SO.
Because the interface defines a single behaviour, while a class can implement several different interfaces and also have features not specified by an interface.
If you want the capabilities of the List<T> class, don't use an IList<T> reference. Use a List<T> reference from the start.
Simply because IList(T) is an interface, while List(T) is one of several classes in the .net bcl that implements IList(T) for the purpose of having indexer functionality. Not all classes that implement IList(T) will require a ConvertAll() method, which is used for converting a generic list of a certain generic type into another.
The IList interface is designed to be implemented far and wide. By omitting convenience methods, that means less work to implement the interface and less opportunity to write bugs.
Fortunately, LINQ side steps this and adds a bunch of useful methods through the "extension method" feature. Select and Cast are particularly useful for conversion purposes. Be sure that you target .NET Framework 3.5, reference the System.Core assembly, and have a using System.Linq; to see it.
Every method or property definition within an interface compels every implementation of the interface to provide code for it. If an interface is implemented by ten thousand classes worldwide, adding to the interface a method which would only take one line of executable code to implement would increase by at least forty thousand lines the total amount of code necessary for all those implementations (assuming normal white-spacing conventions). By contrast, adding a helper method to a class imposes no requirements on interfaces that implement it.
Incidentally, one of my major wish-list items for .net would be a means by which an interface could declare members as having a default implementation via static method (e.g. IFoo which includes member string Boz(int param) could specify that if the code for a class which seeks to implement IFoo doesn't include that member, either the compiler or run-time should auto-generate method string IFoo.Boz(int param) { return IFoo_Helpers.Boz(this, param);}. Had such a method facility existed in .net from version 2.0, it could have probably saved hundreds of thousands, if not million, of lines of code by now, just by having IEnumerable<T> include a default implementation IEnumerator IEnumerable.GetEnumerator() {return IEnumerable_Helpers<T>.GetEnumerator(this);}, with the latter method simply being static IEnumerable GetEnumerator(IEnumerable<T> it) {return it.GetEnumerator();}. Such a feature would have allowed interfaces to offer many more features to their consumers without imposing any more work on their implementers. Further, unlike extension methods which must be statically-bound at the call site, such interface methods would be bound at the implementation, thus allowing implementation-specific overrides to be used when appropriate (for example, if IEnumerable<T> offered a ToList method, List<T> could define a fast implementation which create a new List<T> pre-initialized to the proper size and use Array.Copy to populate it, and implementations of IEnumerable<T> which would return endless sequences could throw an exception (rather than gobbling up all the memory they could get), but most implementations wouldn't have to do anything with that method--they could simply defer to the default general-purpose helper function that would enumerate the items into a new List<T> and let it grow as needed.
or the other way around?
I use generic lists all the time. But I hear occasionally about IEnumerables, too, and I honestly have no clue (today) what they are for and why I should use them. So, at the risk of having something on the net forever more proclaiming my ignorance, I humbly post this question.
Well, List<T> implements IEnumerable<T>... basically IEnumerable<T> is just a sequence of items. You can read through it, and that's all.
List<T> is a mutable collection - you can add to it, remove from it, sort it etc. It's more flexible in itself, but IEnumerable<T> allows you to use the same code to work with any implementation (arrays, linked lists, lists, iterators returned from methods using yield statements etc).
IEnumerable<T> is a more general interface, so you can substitute anything that implements that interface for your operation. If you have this method:
public void DoSomething(IEnumerable<T> enumerable) {
}
It will work on arrays, collections, lists, dictionaries, and anything else that implements the interface.
If you specify that the object is a List<T>, the method will only work on List<T> objects or instances that inherit from it.
The advantage of using List<T> is that lists have many more features than enumerables. When you need those features (insertion, searching, conversion, and many more), List<T> or IList<T> is more appropriate.
John Skeet and others have offered a good synopsis of the functionality of List over IEnumerable, so I thought I'd fill in the other half of the question which is "What are the benefits of using IEnumerable over List?".
First, IEnumerable provides a more generic contract for representing a collection of things you can iterate over and therefore allows you to adhere to the Principle of Least Privilege. In other words, IEnumerable should be preferred over its derived types where enumeration is the only behavior that needs to be exposed for the task at hand. This is beneficial because exposing information and/or behavior unnecessarily opens your API up to possible unintended usages which can pose a security issue or can cause unintended coupling between your API and its consumers.
Second, IEnumerable is an abstraction for enumeration whereas List is one implementation of that abstraction. Following the guidance of Design Patterns - Elements of Reusable Object-Oriented Software, programming to abstractions over implementations aids in making applications more resilient to change by allowing implementations to be changed later without impacting consuming code. If you do need list behavior, you should expose IList rather than List directly.
The biggest advantages of List<T> over IEnumerable<T> are the following
Random access
Count property
ForEach method
Mutability
The first 2 are easy to do on IEnumerable<T> as well but you can't guarantee O(1) speed. In the case of Count you can't even guarantee a real answer as IEnumerable<T> can easily represent infinite lists.
List provides additional methods over IEnumerable. You can't add insert or delete with IEnumerable, but you can with List.
IEnumerable should be used when you plan on looping through the data only. It gives you an advantage over IList, because you don't have to load all the data at once to pass access to the data, you just have to be able to get the next record through the enumerator. IEnumerable is also an interface, so you can "hide" the type of the actual object containing the data List, Array etc.
If you only need the functionality exposed and implemented in IEnumerable<T>, you should go with that. An alternative is IEnumerable<T> where T : IFoo if you want to be able to iterate over objects that implements the interface IFoo. If you, however, require properties like Count and such that List<T> exposes, you should go for that. Find the lowest common denominator and go with that as it makes your methods more versatile and easier to work with.
IEnumerable has a clean read-only and 'enumerable' or 'queriable' semantics. With List it looks like you allow anybody modify it:).
One advantage to IEnumerable that hasn't yet been mentioned: Contravariance. A routine expecting an IEnumerable(Of Car) will be perfectly happy if given an IEnumerable(Of HondaCivic), which in turns means it would be happy with an IList(Of HondaCivic). By contrast, a routine which expects an IList(Of Car) will not be satisfied with an IList(of HondaCivic). If Microsoft IList were derived from a read-only IReadableByIndex interface, then code which expected an IReadableByIndex(Of Car) would be perfectly happy with IReadableByIndex(Of HondaCivic), but that's water under the bridge.