Using IList and ICollection Interfaces
In my last article, I explained, how can we iterate upon a collection to traverse or enumerate its items using the IEnumerable and IEnumerator interfaces along with their generic conterparts. However, those interfaces have some limitations, for instance we could only traverse the collection in forward direction using those interfaces; we could not get the count of collection neither we were able to get an element by specifying the index of the element. Apart from that we could not modify or search the collection. For these functionalities, .NET framework has some other framework including IList, ICollection & IDictionary interfaces. An interesting thing to note here is that unlike IEnumerator and IEnumerable interfaces; the IList <T> and ICollection<T> interface do not inherit from their non-generic counterparts. In fact in most of the cases, IList and ICollection interfaces are used only for legacy systems that still use non-generic collections. In this article, we will explain what the declarations of these interfaces are and how these interfaces can be implemented in programs.
First, let us briefly distinguish between IList<T>, ICollection<T> and IEnumerable <T> interfaces. IEnumerable<T> and IEnumerable interfaces provides the basic functionality, or in other words, the minimum functionality. It allows you to enumerate and traverse elements of a collection. ICollection<T> and ICollection interfaces slightly enhance the capabilities of IEnumerable interfaces and some other functionality such as counting the numbers in a collection etc. IList <T> (also IList) and IDictionary<T> (also IDictionary) are the most advanced of the aforementioned interfaces. These interfaces provide the ability to search an element in the collection based on index or the key.
The ICollection<T> along with its non-generic counterpart provides medium level capabilities on collections which are as follows.
The declaration of the ICollection<T> interface is as follows
Now come to the main method, here we created three objects of Employee class and named them obj1, obj2 and obj3. We initialized these objects with some values.
You must be wondering about the next line i.e
In the next line, we have added the objects obj1, obj2 and obj3 into the EmployeeCollection using the Add method by virtue of HashSet<T>implementing the ICollection<T> interface. Next we have called another property of the ICollection<T> interface i.e Count to display the total number of elements in the EmployeeCollection, which would be three.
Now next lines of code are extremely interesting, we have called GetEnumerator() method on the EmployeeCollection collection. Because this collection implements the ICollection<T> interface, which inherits from the IEnumerable<T> interface, we can call the GetEnumerator method to get the enumerator and store it in IEnumerable<T> interface’s object. We have named this object ‘numer’.
We have then called MoveNext() method inside a while loop so that while loop keeps executing until all the elements in the collection have been traversed. Inside the loop we called Current property of the ‘numer’ object to fetch the current object and then we stored it inside an Employee object ‘emp’. From this ‘emp’ object, we displayed the Name and Age properties of the object. You can see that how we can use ICollection<T> interface to count the elements in a collection and add elements to them as well. You can also call other methods of the ICollection <T> interface on the EmployeeCollection. For example if you want to check that whether the collection contains ‘obj1’ or not you can do something like
EmployeeCollection.Contains(obj1) // Will return true because collection contains obj1
Similarly, you can try other ICollection<T> interface’s methods to better understand the concept. In Example1, EmployeeCollection was not read only. If you call add, clear or remove methods on a read only collection, an exception named NotSuppertedException would be thrown.
As aforementioned, the IList<T> along with its non-generic counterpart IList provides maximum functionalities over a collection. These interfaces allow to read and write element based on the index or position and it also allows us to insert and remove elements via index. These capabilities are not available in the ICollection<T> and IEnumerable<T> interfaces. An important thing to note here is that IList <T> interface inherits ICollection<T> and IEnumerable<T> interfaces, therefore it contains all the functionalities of those interfaces.
Before dwelling into further details regarding the usage and implementation of IList<T> interface, let us first have a look at its declaration.
Now let us come towards the declaration of IList interface. This interface has more methods. Since it only implements the non-generic ICollection and IEnumerable interfaces it has more functionalities of its own. The declaration of IList is as follows.
Now, come inside the main method. We have initialized three objects of Employee class and we have named these objects obj1, obj2 and obj3. Then we simply called the ‘Count’ property in order to display the number of elements in the EmployeeCollection collection.
The next lines are what differentiate this example from the Example2. Consider this line of code
In the next three lines, we have called the IndexOf() method on the EmployeeCollection instance and have passed the three objects that we added previously i.e obj1, obj2 and obj3. We then call the RemoveAt() method on the Employee collection and passed it the index 1. An important thing to note here is that, the collection indexes start from ‘0’ which means that the first element would be on 0th index and the 2nd element would be stored in the first index. So when we call the RemoveAt(1) on EmployeeCollection, the obj2 would be removed because it is stored at the first index.
After that, we have initialized a new Employee object obj4 and have inserted it into collection at the first index using the method Insert(1, obj4). Now we have three objects, obj1 at 0th index, obj4 at 1st index and obj3 at second index.
Next, In order to check that obj2 has really been removed from the first index, we have called the Contains() method and passed it the obj2. It should return false. After that we have got the enumerator of the EmployeeCollection class by calling GetEnumerator in this collection and then have traversed each object using the MoveNext() method and ‘Current’ property of IEnumerator<T> interface which is implemented by IList<T> interface. The output of the code is as follows.
In the output, first of all the number of element in the collection are displayed which are three i.e obj1, obj2 and obj3 at the moment. Next we have displayed their indexes which are 0, 1 and 2 respectively. And then we have displayed their names and ages. Note that the name and age of the second object (Object at first index) is ‘jess’ and ‘21’ respectively. This is due to the reason that we had removed the obj2 from first index and had inserted obj4 at that index, therefore the values of obj4 are being shown in the second row.
The ICollection<T> and IList<T> interfaces, along with their generic counterparts are extremely useful, particularly in cases where you more advanced capabilities as compared to IEnumerable<T> and IEnumerable. In this article we have explained the detailed declaration and implementation of both the aforementioned interfaces. If you have any further question, feel free to comment.
|All times are GMT +5.5. The time now is 02:16.|