CodeGym /Courses /C# SELF /Index Access Contract: ILi...

Index Access Contract: IList<T>

C# SELF
Level 28, Lesson 3
Available

1. Introduction

So, imagine this: you have a collection... and you need to quickly grab the third, seventh, or, say, the zero-th element. Or swap them around. In an array, that's easy — by index (array[3]). But what about collections? Not all collections are equally indexable!

That's where the IList<T> interface comes in — a universal contract that requires a collection to support working with elements by index. In short: if you have a collection that implements IList<T>, you can safely access its elements by index (just like an array) and change them on the fly.

Analogy:
Think of a library card: every book has its own number on the shelf, and you can always walk up to the "third in line" book and grab it. That's how a collection that supports IList<T> behaves.

2. General Structure and Methods of IList<T>

The IList<T> interface is the hero of many collections. It extends ICollection<T> (which in turn extends IEnumerable<T>, letting you loop through the collection), and adds the most important thing: index access.

Interface inheritance diagram:


IEnumerable<T>
      ▲
      │
ICollection<T>
      ▲
      │
  IList<T>
Collection interface inheritance in .NET

Main members of the IList<T> interface

Member Purpose
T this[int index] { get; set; }
Get or set an element by index
int IndexOf(T item)
Find the index of the first occurrence of an element
void Insert(int index, T item)
Insert an element at a given position
void RemoveAt(int index)
Remove an element by index

All the other members, like Add, Remove, Clear, Contains, come from the ICollection<T> interface.

Key feature: the indexer

The main "thing" about IList<T> is the indexer. It's that syntactic sugar that lets you write:


var myList = new List<int> { 10, 20, 30 };
int secondValue = myList[1]; // Gets 20
myList[2] = 42;              // Changes the third element

3. Which collections implement IList<T>

In the standard .NET library, a bunch of familiar structures support the IList<T> interface. Let's check out the most popular ones:

Collection Indexable Description
List<T>
Yes Dynamic array
T[]
Yes Regular arrays are indexable
BindingList<T>
Yes Used for data binding
ObservableCollection<T>
Yes List with notifications
Collection<T>
Yes Base class for collections

Heads up:

LinkedList<T>
and
HashSet<T>
DO NOT implement IList<T>, because they don't have fast indexing (yep, LinkedList<T> doesn't have list[5]!).

4. Examples of using IList<T>

Getting and setting by index


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        IList<string> fruits = new List<string> { "Apple", "Banana", "Pear" };

        // Get the second element
        string fruit = fruits[1];
        Console.WriteLine(fruit); // Banana

        // Replace the third element
        fruits[2] = "Orange";
        Console.WriteLine(fruits[2]); // Orange
    }
}

Insert and remove by index


fruits.Insert(1, "Kiwi");    // Insert "Kiwi" at the second position
// List is now: "Apple", "Kiwi", "Banana", "Orange"

fruits.RemoveAt(0);          // Remove the first element ("Apple")
// List is now: "Kiwi", "Banana", "Orange"

Finding the index of an element


int index = fruits.IndexOf("Orange"); // Returns index (2) or -1 if not found
if (index != -1)
    Console.WriteLine("Orange is at position: " + index);
else
    Console.WriteLine("Orange not found");

5. Implementation quirks and common mistakes

When working with IList<T>, it's easy to fall into a couple of "traps," especially if you forget that indexing starts at zero, and the collection's length is the actual number of elements.

For example, trying to access a non-existent element:


Console.WriteLine(fruits[100]); // IndexOutOfRangeException!

Indexes in C# are like egg-laying hens: they start at zero, not one. If your list has 4 elements, the last available index is 3.

Also, keep in mind that not all IList<T> implementations are equally fast. For example, arrays or List<T> have instant index access (O(1)), but if you made your own collection based on a linked list and for some reason slapped IList<T> on it, the operation could get slow. Though the standard library doesn't do that.

And another thing: if you work with an array as an IList<T>, you can change elements, but you can't change the array's size. Methods like Add, Remove, Insert, etc. for arrays will throw a NotSupportedException.


int[] myArray = { 1, 2, 3 };
IList<int> listView = myArray; // Upcast

listView[0] = 42; // Works!
listView.Add(99); // Throws NotSupportedException

6. Practical use and why you need this

In real projects, almost every other collection is something that implements IList<T>, because it's super handy to quickly access elements by number, change them, insert and remove by position. For example:

  • Interface properties in WPF or WinForms ViewModel, where UI element lists are bound.
  • Implementing sorting, searching, or permutation algorithms where you need index access.
  • Import/export modules that work with a dynamic list of objects.

At an interview the question about the differences between IEnumerable<T>, ICollection<T>, and IList<T> is a classic. Knowing what each level is for, you can confidently explain to the interviewer why HashSet<T> doesn't implement IList<T> (because uniqueness is more important than order and indexes!).

2
Task
C# SELF, level 28, lesson 3
Locked
Working with Insert and IndexOf Methods
Working with Insert and IndexOf Methods
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION