tags:

views:

3008

answers:

9

I know that IList is the interface and List is the concrete type but I still don't know when to use each one. What I'm doing now is if I don't need the Sort or FindAll methods I use the interface. Am I right? Is there a better way to decide when to use the interface or the concrete type?

+1  A: 

I don't think there are hard and fast rules for this type of thing, but I usually go by the guideline of using the lightest possible way until absolutely necessary.

For example, let's say you have a Person class and a Group class. A Group instance has many people, so a List here would make sense. When I declare the list object in Group I will use an IList<Person> and instantiate it as a List.

public class Group {
  private IList<Person> people;

  public Group() {
    this.people = new List<Person>();
  }
}

And, if you don't even need everything in IList you can always use IEnumerable too. With modern compilers and processors, I don't think there is really any speed difference, so this is more just a matter of style.

swilliams
A: 

In situations I usually come across, I rarely use IList directly.

Usually I just use it as an argument to a method

void ProcessArrayData(IList almostAnyTypeOfArray)
{
    // Do some stuff with the IList array
}

This will allow me to do generic processing on almost any array in the .NET framework, unless it uses IEnumerable and not IList, which happens sometimes.

It really comes down to the kind of functionality you need. I'd suggest using the List class in most cases. IList is best for when you need to make a custom array that could have some very specific rules that you'd like to encapsulate within a collection so you don't repeat yourself, but still want .NET to recognize it as a list.

Dan Herbert
+2  A: 

If you're working within a single method (or even in a single class or assembly in some cases) and no one outside is going to see what you're doing, use the fullness of a List. But if you're interacting with outside code, like when you're returning a list from a method, then you only want to declare the interface without necessarily tying yourself to a specific implementation, especially if you have no control over who compiles against your code afterward. If you started with a concrete type and you decided to change to another one, even if it uses the same interface, you're going to break someone else's code unless you started off with an interface or abstract base type.

Mark Cidade
A: 

You should use the interface only if you need it, e.g., if your list is casted to an IList implementation other than List. This is true when, for example, you use NHibernate, which casts ILists into an NHibernate bag object when retrieving data.

If List is the only implementation that you will ever use for a certain collection, feel free to declare it as a concrete List implementation.

Jon Limjap
+4  A: 

It's always best to use the lowest base type possible. This gives the implementer of your interface, or consumer of your method, the opportunity to use whatever they like behind the scenes.

For collections you should aim to use IEnumerable where possible. This gives the most flexibility but is not always suited.

tgmdbm
+22  A: 

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>.

Lee
You shouldn't treat input/output types any differently. Input and output types should *both* be the most basic type (preferably interface) that will support clients needs. Encapsulation relies on telling clients as little about the implementation of your class as possible. If you return a concrete List, you can't then change to some other better type without forcing all of your clients to re-compile/update.
Ash
+6  A: 

I would agree with Lee's advice for taking parameters, but not returning.

If you specify your methods to return an interface that means you are free to change the exact implementation later on without the consuming method ever knowing. I thought I'd never need to change from a List<T> but had to later change to use a custom list library for the extra functionality it provided. Because I'd only returned an IList<T> none of the people that used the library had to change their code.

Of course that only need apply to methods that are externally visible (i.e. public methods). I personally use interfaces even in internal code, but as you are able to change all the code yourself if you make breaking changes it's not strictly necessary.

ICR
+3  A: 

Microsoft guidelines as checked by FxCop discourage use of List<T> in public APIs - prefer IList<T>.

Incidentally, I now almost always declare one-dimensional arrays as IList<T>, which means I can consistently use the IList<T>.Count property rather than Array.Length. For example:

public interface IMyApi
{
    IList<int> GetReadOnlyValues();
}

public class MyApiImplementation : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        List<int> myList = new List<int>();
        ... populate list
        return myList.AsReadOnly();
    }
}
public class MyMockApiImplementationForUnitTests : IMyApi
{
    public IList<int> GetReadOnlyValues()
    {
        IList<int> testValues = new int[] { 1, 2, 3 };
        return testValues;
    }
}
Joe
I like this explanation / example the most!
JonH
+1  A: 

You are most often better of using the most general usable type, in this case the IList or even better the IEnumerable interface, so that you can switch the implementation conveniently at a later time.

However, in .NET 2.0, there is an annoying thing - IList does not have a Sort() method. You can use a supplied adapter instead:

ArrayList.Adapter(list).Sort()
petr k.