Differences between the IEnumerable, ICollection and IList interfaces

IEnumerable, ICollection, and IList are the interfaces most commonly used in the .Net Framework. Let's see what opportunities they open up for the developer.

IEnumerable is the basis for the ICollection and IList interfaces (as well as many others). All these interfaces provide different functionalities and are useful in different cases.

IEnumerable interface

We use IEnumerable when we want to loop through our classes using a foreach loop

The IEnumerable interface has one method, GetEnumerator, which returns the IEnumerator interface and helps to enumerate the class using a foreach loop. The IEnumerator interface implements two methods MoveNext() and Reset(), and has one property Current, which returns the current item in the list.

Let's create a StoreData class to store data of integer type, this class implements the IEnumerable interface. Inside we use a linked list to store data:

class StoreData : IEnumerable
{
    LinkedList<int> items = new LinkedList<int>();
    public void Add(int i)
    {
       items.AddLast(i);
    }
    public IEnumerator GetEnumerator()
    {
       foreach (var item in items)
       {
          yield return item;
       }
    }
}

The code above has created its own storage list where we can store integers (it is practically possible to store any type of data depending on our requirements). We can use the previous list as:

static void Main(string[] args)  
{  
    StoreData list = new StoreData();  
    list.Add(1);  
    list.Add(2);  
    list.Add(3);  
    list.Add(4);  
  
    foreach (var item in list)  
    {  
        Console.WriteLine(item);  
    }  
              
    Console.ReadLine();  
}  

The preceding code will display all values using a foreach loop. You can also use the following code instead of the foreach loop:

IEnumerator enumerator = list.GetEnumerator();  
  
while (enumerator.MoveNext())  
{  
   Console.WriteLine(enumerator.Current);  
}

The foreach loop works the same way as in the previous code. The GetEnumerator() method is available with the list object because it implements the IEnumerable interface.

Then, using the MoveNext() method and the Current property of the StoreData class, we can display the data.

Please note!

Each collection within the .Net Framework implements the IEnumerable interface

Key points of the IEnumerable interface

It provides read-only access to collections. We cannot change any item within an IEnumerable list. It provides a kind of encapsulation in cases where we don't want our list to change.

If we deal with some SQL queries dynamically, this also provides lazy loading. This means that queries will not be executed until we explicitly need them.

ICollection interface

ICollection inherits from the IEnumerable interface, which means that any class that implements the ICollection interface can also be numbered using a foreach loop.

In the IEnumerable interface, we don't know how many elements are in the collection. But the ICollection interface gives us this extra property to get the number of items in the collection. ICollection Interface contains the following:

  • Count Property 
  • IsSynchronized Property
  • SyncRoot Property
  • CopyTo Method

The Count property is used to maintain the number of items in the list. The IsSysnchronized and SyncRoot properties help to make the collection thread-safe. And the CopyTo method copies the entire collection into an array.

The generic version of this interface also provides Add and Remove methods.

IList interface

IList implements the ICollection and IEnumerable interfaces. It allows us to add and remove items from the collection, and provides support for accessing items from the index. This interface is more powerful than the previous two.

The IList interface contains the following:

  • IsFixedSize Property
  • IsReadOnly Property
  • Indexer
  • Add Method
  • Clear Method
  • Contains Method
  • Indexof Method
  • Insert Method
  • Remove Method
  • RemoveAt Method

The IList interface has a single indexer with which we can access any element by its position, and we can insert an element and delete it at any position.