When To Use IEnumerable Or ICollection Or IList Or List

Generally, developers are confused about when and why should they use IEnumerable OR ICollection OR IList Or List. So, in this article, I am exploring more when and why to use each.

When and why we should choose IEnumerable

This is the base interface for any collection under system.Collection. If you want iteration only, then it is the best choice to use. Iteration means that you do not want any index based search or any write or any insert or remove.(only read records). You can only read records, nothing else.
  1. public interface IEnumerable {  
  2.     // Summary:  
  3.     // Returns an enumerator that iterates through a collection.  
  4.     //  
  5.     // Returns:  
  6.     // An System.Collections.IEnumerator object that can be used to iterate through  
  7.     // the collection.  
  8.     [DispId(-4)]  
  9.     IEnumerator GetEnumerator();  
  10. }  
IEnumerable contains only GetEnumerator() method, like read-only iterate.

When and why we should use ICollection

ICollection is one step ahead of IEnumerable. If we want some more functionality like Add or remove element, then it is better to go with ICollection because we cannot achieve that with IEnumerable. ICollection extends IEnumerable. It supports non-index based operations like - Add item in Collection, remove, check contained item etc. ICollection has "Add" method (see in screenshot 2). So, there is not any index as a parameter to insert or remove element at a particular index.
  1. [ComVisible(true)]  
  2. public interface ICollection: IEnumerable {  
  3.     int Count {  
  4.         get;  
  5.     }  
  6.     bool IsSynchronized {  
  7.         get;  
  8.     }  
  9.     object SyncRoot {  
  10.         get;  
  11.     }  
  12.   
  13.     void CopyTo(Array array, int index);  
  14. }  
When and why we use IList

This is the only interface in the System.Collection that contains all functionality of IEnumerable and ICollection and additional functionality.

As you are seeing in the below code, IList has Insert and Remove methods. Both the methods accept index in their parameter. So, it supports index based operations over collection.

IList is the last interface in the hierarchy of all collection interfaces. It extends ICollection.
  1. [ComVisible(true)]  
  2. public interface IList: ICollection, IEnumerable {  
  3.     bool IsFixedSize {  
  4.         get;  
  5.     }  
  6.     bool IsReadOnly {  
  7.         get;  
  8.     }  
  9.     int Add(object value);  
  10.     void Clear();  
  11.   
  12.     bool Contains(object value);  
  13.     int IndexOf(object value);  
  14.     void Insert(int index, object value);  
  15.     void Remove(object value);  
  16.     void RemoveAt(int index);  
  17. }  
  18. IList can accept any kind of Collection Example we can pass  
  19. List < string > lst = new List < string > ();  
  20. IList < string > str = lst;  
  21. OR  
  22. string[] arr = new string[] {  
  23.     "one",  
  24.     "two",  
  25.     "three"  
  26. };  
  27. IList < string > str = arr;  
  28. OR  
  29. ArrayList lst = new ArrayList();  
  30. lst.Add("tanuj");  
  31. IList str = lst;  
When and why we use IList , why IList and Not List

List is the concrete class. This class implements IList, ICollection, IEnumerable. IList provides us full flexibility to expose any method that list implements.

If we are making a class library and providing the DLL to two different clients to expose functionality, it's easy to make any change in interface rather than class. Below is the example .

If we expose Class OR LIST outside the world, it is more difficult to handle every client that is using the same functionality. So, never change in concrete class. Always expose interface.

Exposing Interface Example

In the below example, we are exposing Interface.
  1. public interface I1 {  
  2.     void Display();  
  3. }  
  4. public class A: I1 {  
  5.     public void Display() {  
  6.         Console.WriteLine("Dislay Calling");  
  7.     }  
  8. }  
  9. static void Main(string[] args) {  
  10.     I1 interfaceExpose = new A();  
  11.     interfaceExpose.Display();  
  12.     }  
So, after some time, one client says I need to add Display2() functionality. Then, we need to add Display2() function in interface and access that method easily.

Here is the Problem with Exposing Class.
  1. public interface I1 {  
  2.     void Display();  
  3. }  
  4. public class A: I1 {  
  5.     Public void Display() {  
  6.         Console.WriteLine("Dislay Calling");  
  7.     }  
  8.     Public void Displat2() // Added Display2() method in Class Client Need  
  9.         {  
  10.   
  11.         }  
  12. }  
  13. static void Main(string[] args) {  
  14.     I1 interfaceExpose = new A();  
  15.     interfaceExpose.Display(); // Calling function outside the world.  
  16.     interfaceExpose.Display2(); // Giving error cannot access Display2() outside // the world. so go for Interface  
  17.   
  18. }  
It gives error that It cannot access Display2 () function.
 
Conclusion
 
Move to expose interface. Never do any changes in concrete class. Leave concrete class  for implementation.