Important Interface in .NET: Work With ICollection Interface

Welcome to the “Important Interface in C#” article series. In this series we will be talking about various useful interfaces of the .NET class library. In our previous article we have talked about the IEnumerable interface, you can read it here.

Important Interface in .NET: Work with Ienumerable Interface

In this presentation we will understand the ICollection interface of the .NET class library. We can say that the ICollection interface is the base interface of all collection types in the .NET library. And the uses of the ICollection interface is every now and then in application development. You might think, no I have never used the ICollection interface in my day-to-day coding life. Let me ask a small question. Have you used List or any other type of collection in .NET? Haha, your answer is yes. Then you have used the ICollection interface without your knowledge.

There are the following two versions of the ICollection interface:

  • ICollection: without parameter
  • ICollection<T>: with parameter of type T

The ICollection interface is located in the following place of the .NET class library:

  • Namespace: System.Collections
  • Assembly: mscorlib.dll

And the ICollection<T> is located in the following location:

  • Namespace: System.collection.Generics
  • Assembly: mscorlib.dll

Here is a different version of the ICollection interface.

Fine, so far we have understood the various versions of the ICollection interface and their location in the .NET class library.

Definition of ICollection and the ICollection<T> interface

There are three properties (all are read only in nature) and one method in the ICollection interface.

public interface ICollection : IEnumerable
{
    int Count { get; }  
    bool IsSynchronized { get; }
    Object SyncRoot { get; }
    void CopyTo(Array array, int index);
}

ICollection inherits from IEnumerable, so that we can iterate an object collection of the ICollection interface (for example List and List<T>) using a foreach loop.

Here is the body of the generic ICollection<T> interface.

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);
}

It contains two read only properties and five methods. We are seeing that ICollection<T> implements IEnumerable<T> and IEnumerable interfaces. Those methods are simple to understand, here I am trying to provide a small description.

  • Add: Adds an item to the ICollection<T>.
  • Clear: Removes all items from the ICollection<T>.
  • Contains: Determines whether the ICollection<T> contains a specific value.
  • CopyTo: Copies the elements of the ICollection<T> to an Array, starting at a specific Array index.
  • GetEnumerator: Returns an enumerator that iterates through the collection. (Inherited from IEnumerable<T>.)
  • Remove: Removes the first occurrence of a specific object from the ICollection<T>.

Example of ICollection<T>

We will now implement an ICollection<T> interface in the following example. As we know T represents type, so we can pass any data type in place of T, it does not matter whether T is user defined or pre-defined. Have a look at the following example.

static void Main(string[] args)
{
    //Premitive data type in place of T in Icollection
    ICollection<string> names = new List<string>();
    names.Add("Sourav Kayal");
    names.Add("Soumen Das");
    names.Add("Rohit");
    var v = from n in names.Where(m=>m.Contains("S")) select n;
    foreach (string s in v)
    {
        Console.WriteLine(s);
    }
    Console.ReadLine();
}

Here is the output of the above example.

In the above example, we passed a predefined data type in place of T but now we will pass a user defined data type (class) in place of T. Here is the sample implementation.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SelfHostingWebAPI
{
    public class Person
    {
        public string name { get; set; }
        public string surname { get; set; }
        public Person(string name, string surname)
        {
            this.name = name;
            this.surname = surname;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Premitive data type in place of T in Icollection
            ICollection<Person> names = new List<Person>();
            names.Add(new Person("Sourav","Kayal"));
            names.Add(new Person("Soumen","Das"));
            Console.WriteLine("Store user defined object in ICollection");
            var v = from n in names.Where(m=> m.name.StartsWith("S")) select n;
            foreach (Person s in v)
            {
                Console.WriteLine(s.name + " " + s.surname);
            }
            Console.ReadLine();
        }
    }
}

The following is the output of the example above.

Ok, we have understood how to use ICollection<T> by passing a predefined and user defined data type as the argument. Now we will implement an ICollection<T> in our own class.

Implement ICollection in own C# class

To implement the Icollection interface in our own class we need to implement all functions and properties of the ICollection interface. Though in this example we did not implement all the methods.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SelfHostingWebAPI
{
    public class Person : ICollection<Person>
    {
        public Int16 ID { get; set; }
        public string name { get; set; }
        public string surname { get; set; }
        Object[] persons = new Object[5];
        Int16 Index = 0;
        public Person()
        {
        }
        public Person(Int16 ID, string name, string surname)
        {
            this.ID = ID;
            this.name = name;
            this.surname = surname;
        }
        public void Add(Person item)
        {
            persons[Index] = item;
            Index++;
        }
        public void Clear()
        {
            persons = null;
        }
        public bool Contains(Person item)
        {
            throw new NotImplementedException();
        }
        public void CopyTo(Person[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }
        public int Count
        {
            get { return Index; }
        }
        public bool IsReadOnly
        {
            get { throw new NotImplementedException(); }
        }
        public bool Remove(Person item)
        {
            //throw new NotImplementedException();
            persons[item.ID] = null;
            return true;
        }
        public IEnumerator<Person> GetEnumerator()
        {
            //throw new NotImplementedException();
            foreach (Person o in persons)
            {
                if (o == null)
                    break;
                else
                    yield return o;
            }
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Person p = new Person();
            p.Add(new Person(1,"Sourav","Kayal"));
            p.Add(new Person(2,"Ram","Kumar"));
            foreach (Person pr in p)
            {
                Console.WriteLine(pr.name + " " + pr.surname);
            }
            Console.ReadLine();
        }
    }
}

Have a look at the GetEmumerator() method that helps to use a foreach loop through the collection of Person classes.

Here is the output of the example above.

Conclusion

In this article, we learned about the ICollection interface. In general, we do not use this interface directly but when we work with any type of collection (almost) in the .NET class library we implicitly use this interface. Happy day. Returning soon with the next presentation in this series.


Similar Articles