C# - IList<T>

IList<T> is an interface in the System.Collections.Generic namespace that represents a collection of objects that can be individually accessed by index. It extends the ICollection<T> interface, which means that it inherits properties and methods of the ICollection<T> interface.

IList<T> has the functionality of ICollection<T>, but in addition, it also supports indexing, adding, removing, and finding items.

Characteristics:

  1. Items can be accessed by index.
  2. Provides methods to search for elements.
  3. Supports adding and removing items.
  4. Can determine the index of an item.

Example:


using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        IList<string> fruits = new List<string>();

        // Adding elements
        fruits.Add("Apple");
        fruits.Add("Banana");
        fruits.Add("Cherry");

        Console.WriteLine("Fruits List:");
        foreach (var fruit in fruits)
        {
            Console.WriteLine(fruit);
        }

        // Accessing element by index
        Console.WriteLine($"\nFruit at index 1: {fruits[1]}");

        // Removing element by index
        fruits.RemoveAt(1);
        Console.WriteLine("\nAfter removing Banana:");
        foreach (var fruit in fruits)
        {
            Console.WriteLine(fruit);
        }

        // Inserting at specific index
        fruits.Insert(1, "Grape");
        Console.WriteLine("\nAfter inserting Grape at index 1:");
        foreach (var fruit in fruits)
        {
            Console.WriteLine(fruit);
        }
    }
}

Output:


Fruits List:
Apple
Banana
Cherry

Fruit at index 1: Banana

After removing Banana:
Apple
Cherry

After inserting Grape at index 1:
Apple
Grape
Cherry

IList<T> Methods and Properties

Properties:
Name Description
Item[int index] Gets or sets the element at the specified index.
Count Gets the number of elements contained in the IList<T>.
IsReadOnly Gets a value indicating whether the IList<T> is read-only.
Methods:
Name Description
Add(T item) Adds an item to the IList<T>. Returns the index at which the item has been added.
Clear() Removes all items from the IList<T>.
Contains(T item) Determines whether the IList<T> contains a specific value.
CopyTo(T[] array, int arrayIndex) Copies the elements of the IList<T> to an array, starting at a particular array index.
IndexOf(T item) Determines the index of a specific item in the IList<T>.
Insert(int index, T item) Inserts an item to the IList<T> at the specified index.
Remove(T item) Removes the first occurrence of a specific object from the IList<T>.
RemoveAt(int index) Removes the IList<T> item at the specified index.
GetEnumerator() Returns an enumerator that iterates through the collection.

Pros of IList<T>:

  • Flexibility: Since IList<T> is an interface, you can implement it in custom classes to offer list-like behaviors while still preserving other unique characteristics of the class.
  • Indexed Access: You can directly access items by their index, which makes certain operations fast.
  • Standardized API: Implementing IList<T> ensures that developers familiar with the .NET collection interfaces will instantly recognize and understand how to use your class.
  • Extensibility: While classes like arrays are fixed in size, classes implementing IList<T> can be designed to grow or shrink as needed.
  • Interoperability: Many built-in .NET Framework methods and LINQ extensions operate on IList<T>, meaning that classes implementing it can readily be used with those methods.

Cons of IList<T>:

  • Performance Overhead: Depending on the specific implementation, certain operations (like inserting an element in the middle of the list or removing it) can be computationally expensive, especially for larger lists.
  • Potential for Misuse: Direct indexed access can lead to out-of-range exceptions if not used with care. This is particularly true when the size of the list can change during operations.
  • Lack of Specificity: Because it's a general-purpose interface, IList<T> doesn't offer specialized methods that might be present in more specialized collections (e.g., priority queues, linked lists).
  • Mutable by Default: The interface provides methods for adding and removing elements, making it unsuitable for scenarios where immutability is desired. Although the list can be made read-only, it's not inherently immutable.
  • Not Thread-Safe: Implementations of IList<T> are not guaranteed to be thread-safe. If multiple threads access an IList<T> instance concurrently, and at least one of the threads modifies the list, it must be synchronized externally.

Difference between IEnumerable and IList:

Aspect IEnumerable IList
Purpose Represents a forward-only cursor of T. Allows iteration over a collection using the foreach loop. Represents a collection that can be individually accessed by index. Provides more functionality than IEnumerable.
Methods and Properties Exposes the GetEnumerator() method. Provides MoveNext(), Reset(), and Current properties for iteration. Inherits from ICollection. Includes methods like Add(), Remove(), RemoveAt(), Insert(), IndexOf() and properties like Item[] and IsReadOnly.
Mutability Doesn’t expose methods that can modify the collection. Suitable for representing read-only sequences. Provides methods to modify the collection. Mutable unless implementation specifically prohibits modification.
Usage Scenarios Suitable for any collection that can be iterated over. Most basic interface for collections in .NET. Used when indexed access or addition/removal/modification of items is needed. Examples: List, ArrayList.
Performance Lightweight and meant for iteration only. Offers O(1) access times for indexed retrieval, though not a strict requirement.
Flexibility More generic and less restrictive. Can represent infinite sequences. Requires a structured and finite collection due to indexed access.
Extensions Can leverage LINQ extension methods. Commonly used with LINQ since LINQ queries return IEnumerable. Can also use LINQ extension methods.

Difference between ICollection and IList:

Aspect ICollection IList
Inheritance Hierarchy Foundational collection interface in .NET. Defines basic behaviors common to all collections. Inherits from ICollection. Adds behaviors specific to collections with indexed access.
Methods and Properties Includes: Count, IsSynchronized, SyncRoot, CopyTo Includes: Item[int index], IsReadOnly, IsFixedSize, Add, Clear, Contains, IndexOf, Insert, Remove, RemoveAt
Usage Scenarios Use for basic collection behaviors like counting items or copying them to an array. Use for indexed access to items or for adding, removing, or modifying items in specific positions.
Mutability Provides basic collection operations. Modification isn't inherently allowed or disallowed. Allows items to be added/removed unless made read-only.
Flexibility Suitable for a broad range of collections: lists, sets, etc. Assumes the collection has order and items can be accessed by index.
Performance Considerations Performance depends on the concrete type that implements it. Typically offers O(1) access times for indexed retrieval. Some operations like Insert or Remove can be O(n).