C#

Generic IList Interface and its Implementation in C#

In this post I will discuss Generic IList Interface and its Implementation in C#. Basically, this interface is represented as IList<T> and it inherits from the generic ICollection and IEnumerable interfaces respectively. Significantly, this interface has applications in creating the generic lists as it provides several important properties and methods.

Details of the IList Interface

The IList interface has a number of properties and methods which we discuss next.

Properties of IList Interface

This interface has three properties. Firstly, the Count property indicates the total number of elements in the list. Secondly, the IsReadOnly property indicates whether the list is readonly or read-write. Finally, the Items property allows us to add elements to the list as well as to read elements from the list. In fact, the IList interface inherits the Count and the IsReadOnly properties from the ICollection interface.

Methods of the IList Interface

The IList interface contains several methods. However, it inherits many of these methods from the ICollection interface. Besides, the IList interface inherits the GetEnumerator() method from the generic IEnumerable interface. Let us discuss these methods one by one.

Add(T obj) method allows us to add a member to the end of the list.

Insert(Int32, T) method takes an index as the first parameter and the object that we want insert as the second parameter. Further, this method inserts the object at specified index if the index is valid.

Contains(T) method is used to search an element which it takes as the parameter and returns a boolean value.

Remove(T) method removes a specific method from the list which is passed as a parameter.

CopyTo(T[], Int32) method copies all the data of the list to an array of specified type starting from a given index.

IndexOf(T) method returns the index of the first occurrence of an element passed as a parameter. Also, if it is not found, the method will return -1.

RemoveAt(Int32) method deletes an element from the specified index.

Clear() method deletes all elements from the list.

GetEnumerator() method returns a custom enumerator.

Generic IList Interface and its Implementation in C#

At this point, let us create a class with the name Employee as shown below. Further, create a list of Employee objects and implement the IList interface for the Employee list.

class Employee
    {
        public string Name { get; set; } = "X";
        public string Designation { get; set; } = "Staff";
        public int Salary { get; set; } = 5000;
        public override string ToString()
        {
            return $"Name: {Name}, Designation: {Designation}, salary: {Salary}";
        }
        public override bool Equals(object obj)
        {
            Employee o = (Employee)obj;
            return Name.Equals(o.Name);
        }
    }

Now create a class called EmpList that implements the generic interface IList as shown below.

class EmpList<Employee>:IList<Employee> {
     }

Define Data Members

Further, define the data members of this class. Therefore, we add the variable cnt to represent the count of elements and the array named staff will have the Employee objects.

class EmpList<Employee>:IList<Employee>
    {
        int cnt = 0;
        Employee[] staff = new Employee[10];
    }

After that, we provide implementation of the GetEnumerator method as shown below. Since, we don’t want to provide a custom enumerator this time, we will not implement this method.

public IEnumerator<Employee> GetEnumerator()
        {
            throw new InvalidOperationException("Employee List is currently not implementing its own enumerator");
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new InvalidOperationException("Employee List is currently not implementing its own enumerator");
        }

Since we are not implementing GetEnumerator right now, the class must have some method to visit the members of the list. Therefore, we provide a method called DisplayList().

public void DisplayList()
        {
            for (int i = 0; i < cnt; i++)
                Console.WriteLine(staff[i]);
        }

Implementation of Properties

Also, our class EmpList should implement three properties namely, Count, IsReadOnly, and the Items property. Therefore, first, implement the Count property. Since it is a readonly property, so it will contain only the get accessor.

public int Count
        {
            get
            {
                return cnt;
            }
        }

Certainly, we want to perform both read and write operations in our list. Hence, the IsReadOnly property should return false.

public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

After that, define the Items property as follows. Basically, it should have both get and set accessors.

public Employee this[int index]
        {
            get
            {
                return staff[index];
            }
            set
            {
                staff[index] = value;
            }
        }

Implementation of Methods

Similarly, we implement the methods of the IList interface as shown below. The Clear() method makes the count of elements to zero and the Add() method will add an element to the list after checking the bounds.

public void Add(Employee e)
        {
            if (cnt < 10)
            {
                staff[cnt] = e;
                cnt++;
            }
        }

        public void Clear()
        {

            cnt = 0;
        }

Evidently, both the Contains() method, and the IndexOf() method check whether the Employee object passed as the parameter is already there in the collection or not. Consequently, the Contains() method returns a boolean value whereas the IndexOf() method returns the corresponding index or -1 depending on whether the element is found or not.

public bool Contains(Employee ob)
        {
            for (int i = 0; i < cnt; i++)
            {
                if (staff[i].Equals(ob))
                    return true;
            }
            return false;
        }
        public int IndexOf(Employee ob)
        {
            for (int i = 0; i < cnt; i++)
            {
                if (staff[i].Equals(ob))
                    return i;
            }
            return -1;
        }

After that, we will define the Insert(), Remove(), and RemoveAt() methods. Basically, the Insert() method will do necessary condition checking and then it will shift some elements to the right before inserting the desired element in the collection. Similarly, the remove() method will shift the elements to the left and decrement the element count by one. However, the Remove() method will call RemoveAt() to delete an element.

 public void Insert(int index, Employee ob)
        {
            if ((cnt + 1 <= staff.Length) && (index >= 0) && (index < cnt))
            {
                cnt++;
                for (int i = cnt - 1; i > index; i--)
                {
                    staff[i] = staff[i - 1];
                }
                staff[index] = ob;
            }
        }
        public bool Remove(Employee ob)
        {
            int p = IndexOf(ob);
            if (p != -1)
            {
                RemoveAt(p);
                return true;
            }
            return false;
        }
        public void RemoveAt(int index)
        {
            if ((index >= 0) && (index < cnt))
            {
                for (int i = index; i < cnt; i++)
                {
                    staff[i] = staff[i + 1];
                }
                cnt--;

            }
        }

Finally, the CopyTo() method copies all the elements of the list to an array of Employee objects starting from a specified index as shown below.

 public void CopyTo(Employee[] arr, int index)
        {
            /*  foreach (Employee e in arr)
                  Console.WriteLine(e);*/
            for (int i = 0; i < cnt; i++)
            {
                arr[index] = staff[i];
                index++;
            }
        }
    }

The Complete Code

Finally, the complete code is shown below.

using System;
using System.Collections.Generic;
using System.Collections;
namespace GenericIListInterfaceExample
{
    class Employee
    {
        public string Name { get; set; } = "X";
        public string Designation { get; set; } = "Staff";
        public int Salary { get; set; } = 5000;
        public override string ToString()
        {
            return $"Name: {Name}, Designation: {Designation}, salary: {Salary}";
        }
        public override bool Equals(object obj)
        {
            Employee o = (Employee)obj;
            return Name.Equals(o.Name);
        }
    }

    class EmpList<Employee> : IList<Employee>
    {
        int cnt = 0;
        Employee[] staff = new Employee[10];
        public IEnumerator<Employee> GetEnumerator()
        {
            throw new InvalidOperationException("Employee List is currently not implementing its own enumerator");
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new InvalidOperationException("Employee List is currently not implementing its own enumerator");
        }
        public void DisplayList()
        {
            for (int i = 0; i < cnt; i++)
                Console.WriteLine(staff[i]);
        }

        public void Add(Employee e)
        {
            if (cnt < 10)
            {
                staff[cnt] = e;
                cnt++;
            }
        }

        public void Clear()
        {

            cnt = 0;
        }

        public int Count
        {
            get
            {
                return cnt;
            }
        }

        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        public Employee this[int index]
        {
            get
            {
                return staff[index];
            }
            set
            {
                staff[index] = value;
            }
        }
        public bool Contains(Employee ob)
        {
            for (int i = 0; i < cnt; i++)
            {
                if (staff[i].Equals(ob))
                    return true;
            }
            return false;
        }
        public int IndexOf(Employee ob)
        {
            for (int i = 0; i < cnt; i++)
            {
                if (staff[i].Equals(ob))
                    return i;
            }
            return -1;
        }
        public void Insert(int index, Employee ob)
        {
            if ((cnt + 1 <= staff.Length) && (index >= 0) && (index < cnt))
            {
                cnt++;
                for (int i = cnt - 1; i > index; i--)
                {
                    staff[i] = staff[i - 1];
                }
                staff[index] = ob;
            }
        }
        public bool Remove(Employee ob)
        {
            int p = IndexOf(ob);
            if (p != -1)
            {
                RemoveAt(p);
                return true;
            }
            return false;
        }
        public void RemoveAt(int index)
        {
            if ((index >= 0) && (index < cnt))
            {
                for (int i = index; i < cnt; i++)
                {
                    staff[i] = staff[i + 1];
                }
                cnt--;

            }
        }

        public void CopyTo(Employee[] arr, int index)
        {
            /*  foreach (Employee e in arr)
                  Console.WriteLine(e);*/
            for (int i = 0; i < cnt; i++)
            {
                arr[index] = staff[i];
                index++;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Employee[] arr = new Employee[]
            {
                new Employee{Name="A", Designation="Manager", Salary=45000},
                new Employee{Name="B", Designation="Cleark", Salary=15000},
                new Employee{Name="C", Designation="Programmer", Salary=35000},
                new Employee{Name="D", Designation="Operator", Salary=25000},
                new Employee{Name="E", Designation="Driver", Salary=15000},
                new Employee{Name="F", Designation="Manager", Salary=50000},
            };

            EmpList<Employee> list1 = new EmpList<Employee>();
            Console.WriteLine($"Count: {list1.Count}");
            Console.WriteLine("Adding Elements...");
            for (int i = 0; i < arr.Length; i++)
            {
                list1.Add(arr[i]);
            }
            Console.WriteLine("List Elements...");
            list1.DisplayList();
            Console.WriteLine($"Count: {list1.Count}");

            Employee e = new Employee { Name = "xyz", Designation = "Clerk", Salary = 17000 };
            Console.WriteLine("Inserting in Employee List...");
            list1.Insert(4, e);
            list1.DisplayList();
            Console.WriteLine($"Count: {list1.Count}");

            Employee e1 = new Employee { Name = "B" };
            Console.WriteLine("Removing an element from the list...");
            list1.Remove(e1);
            list1.DisplayList();
            Console.WriteLine($"Count: {list1.Count}");

            Console.WriteLine("Removing another element from the list...");
            list1.RemoveAt(5);
            list1.DisplayList();
            Console.WriteLine($"Count: {list1.Count}");

            Employee[] arr1 = new Employee[20];
            for (int i = 0; i < 20; i++)
                arr1[i] = new Employee();
            Console.WriteLine("CopyTo method...");
            list1.CopyTo(arr1, 7);
            Console.WriteLine("Resulting Array...");
            foreach (Employee ob in arr1)
                Console.WriteLine(ob);

            Console.WriteLine("Searching Elements in the list...");
            Employee e3 = new Employee { Name = "A" };
            Employee e4 = new Employee { Name = "S" };
            Console.WriteLine($"Employee List Contains A: {list1.Contains(e3)}");
            Console.WriteLine($"Employee List Contains S: {list1.Contains(e4)}");

            Employee e5 = new Employee { Name = "E" };

            Console.WriteLine($"Index of A: {list1.IndexOf(e3)}");
            Console.WriteLine($"Index of S: {list1.IndexOf(e4)}");
            Console.WriteLine($"Index of E: {list1.IndexOf(e5)}");

            Console.WriteLine($"Is List Read Only: {list1.IsReadOnly}");

            Console.WriteLine("Clearing the List...");
            list1.Clear();
            list1.DisplayList();
            Console.WriteLine($"Count: {list1.Count}");
        }
    }
}

Output

Demonstration of Add(), Insert(), Remove(), and RemoveAt() Methods
Demonstration of Add(), Insert(), Remove(), and RemoveAt() Methods
Demonstration of Clear(), IndexOf(), Contains(), and CopyTo() Methods
Demonstration of Clear(), IndexOf(), Contains(), and CopyTo() Methods

Summary

To sum up, this article on Generic IList Interface and its Implementation in C# shows how to implement this interface for a collection containing user-defined types. Basically, we need to provide the implementation of each property and method declared in this interface.


Related Topics

A Beginner’s Tutorial on WPF in C#

Everything about Tuples in C# and When to Use?

Linear Search and Binary Search in C#

Creating Jagged Arrays in C#

Learning Indexers in C#

Understanding Method Parameter Modifiers in C#

Object Initializers in C#

Examples of Static Constructors in C#

When should We Use Private Constructors?

C# Practice Questions

C# Basic Examples

Private and Static Constructors in C#

Constructors in C#

C# Arrays

C# Examples

How to Create a C# Console Application

Creating Navigation Window Application Using WPF in C#

LINQ To SQL Examples

Understanding the Concept of Nested Classes in C#

How to Setup a Connection with SQL Server Database in Visual Studio

Examples of Extension Methods in C#

Learning All Class Members in C#

Access Modifiers in C#

C# Root Class – Object

KeyValuePair and its Applications

IEnumerable and IEnumerator Interfaces

IEqualityComparer Interface

New Features in C# 9

Leave a Reply

Your email address will not be published. Required fields are marked *