When to Use Ilist and When to Use List

When to use IList and when to use List

There are two rules I follow:

  • Accept the most basic type that will work
  • Return the richest type your user will need

So when writing a function or method that takes a collection, write it not to take a List, but an IList<T>, an ICollection<T>, or IEnumerable<T>. The generic interfaces will still work even for heterogenous lists because System.Object can be a T too. Doing this will save you headache if you decide to use a Stack or some other data structure further down the road. If all you need to do in the function is foreach through it, IEnumerable<T> is really all you should be asking for.

On the other hand, when returning an object out of a function, you want to give the user the richest possible set of operations without them having to cast around. So in that case, if it's a List<T> internally, return a copy as a List<T>.

Why use IList or List?

There are three questions here: what type should I use for a formal parameter? What should I use for a local variable? and what should I use for a return type?

Formal parameters:

The principle here is do not ask for more than you need. IEnumerable<T> communicates "I need to get the elements of this sequence from beginning to end". IList<T> communicates "I need to get and set the elements of this sequence in arbitrary order". List<T> communicates "I need to get and set the elements of this sequence in arbitrary order and I only accept lists; I do not accept arrays."

By asking for more than you need, you (1) make the caller do unnecessary work to satisfy your unnecessary demands, and (2) communicate falsehoods to the reader. Ask only for what you're going to use. That way if the caller has a sequence, they don't need to call ToList on it to satisfy your demand.

Local variables:

Use whatever you want. It's your method. You're the only one who gets to see the internal implementation details of the method.

Return type:

Same principle as before, reversed. Offer the bare minimum that your caller requires. If the caller only requires the ability to enumerate the sequence, only give them an IEnumerable<T>.

ListT or IListT

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.

Why to use interface IList to create an object of List type?

A List is a concrete type, while an IList is a contract for which you can use any implemtation that an IList has.

An IList has a set of methods as defined on MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ilist.aspx

Here's a very good blogpost explaining it in detail: http://www.claudiobernasconi.ch/2013/07/22/when-to-use-ienumerable-icollection-ilist-and-list/

Sample Image

Why should I return IListT over ListT?

The reason is so that your method can be used with anything that implements IList<T>, and not just a List. It gets even worse, though, since the advent of Linq, I've started making a lot of stuff return Enumerable<T> or even just IEnumerable!

I am not sure I understand the difficulty, though. If something is returning an actual list, and its return depends on that, or its use is specific to that, then it should return List<T>. If not, then you should have no need to cast it to a List.

Comparison between List, IList, and IEnumerable

  • IEnumerable<T> is the base interface that the following extend or implement. It doesn't allow for direct access and is readonly. So use this only if you intend to iterate over the collection.

  • ICollection<T> extendsIEnumerable<T> but in addition allows for adding, removing, testing whether an element is present in the collection and getting the total number of elements. It doesn't allow for directly accessing an element by index. That would be an O(n) operation as you need to start iterating over it until you find the corresponding element.

  • IList<T> extends ICollection<T> (and thus it inherits all its properties) but in addition allows for directly accessing elements by index. It's an O(1) operation.

  • List<T> is just a concrete implementation of the IList<T> interface.

In your code you should always expose the type that's highest in the object hierarchy that will correspond to the needs of the callers. So for example if the callers are only going to enumerate over the dataset, use IEnumerable<T>. If they need to have direct access to elements by index expose an IList<T>.

List<T> should only be used internally by your code but usually not present in the signature of the methods you are exposing. This gives you more flexibility as you could easily swap the concrete implementation without breaking the contract.



Related Topics



Leave a reply



Submit