Difference between IEnumerable, ICollection, IList and IQueryable. Did you know?

2022, May 27

Did you know the difference between IEnumerable, ICollection, IList and IQueryable? Often we implement these interfaces to use with Collections, without understanding the interfaces. According to the Interface Segregation principle (ISP)1, it is better to have (and use) more specific interfaces than general-purpose interfaces.

Let's have a look at the interfaces, their contracts and specific characteristics.

Interfaces

Depending on the purpose of the implementation you are after, the different interfaces provide flexibility to choose. The fatter the interface, the more maintenance is to keep.

IEnumerable

This interface only allows the iteration over the elements in a collection. It comes from the namespace System.Collections.

With Linq, it uses Linq to Objects, which means that all objects are loaded into memory from database, independent of the query. If filtering is applied to the original query, it is only executed after the objects are already loaded in memory.

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

ICollection

This interface extends IEnumerable and also allows the modification of collections. It comes from the namespace System.Collections.

public interface ICollection : IEnumerable
{
    void CopyTo(Array array, int index);

    int Count { get; }

    object SyncRoot { get; }

    bool IsSynchronized { get; }
}

public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
    int Count { get; }

    bool IsReadOnly { get; }

    void Add(T item);

    void Clear();

    bool Contains(T item);

    void CopyTo(T[] array, int arrayIndex);

    bool Remove(T item);
}

IList

This interface extends IEnumerable and ICollection. It allows the manipulation of the collection, the positioning and the order of the collection. It comes from the namespace System.Collections.

public interface IList : ICollection, IEnumerable
{
    object? this[int index] { get; set; }

    int Add(object? value);

    bool Contains(object? value);

    void Clear();

    bool IsReadOnly { get; }

    bool IsFixedSize { get; }

    int IndexOf(object? value);

    void Insert(int index, object? value);

    void Remove(object? value);

    void RemoveAt(int index);
}

public interface IList<T> : ICollection<T>, IEnumerable<T>, IEnumerable
{
    T this[int index] { get; set; }

    int IndexOf(T item);

    void Insert(int index, T item);

    void RemoveAt(int index);
}

IQueryable

This interface extends IEnumerable. It comes from the namespace System.Linq.

With Linq, it converts Linq expression to SQL statement, by applying filters at the database layer and returning filtered records.

public interface IQueryable : IEnumerable
{
    Expression Expression { get; }

    Type ElementType { get; }

    IQueryProvider Provider { get; }
}

public interface IQueryable<out T> : IEnumerable<T>, IEnumerable, IQueryable
{
}