JavaRush /Курсы /C# SELF /Контракт на доступ по индексу:

Контракт на доступ по индексу: IList<T>

C# SELF
28 уровень , 3 лекция
Открыта

1. Введение

Итак, представьте себе: у вас есть коллекция… а вам нужно быстро получить третий, седьмой или, скажем, нулевой элемент. Или поменять их местами. В массиве это делается легко — по индексу (array[3]). А что насчёт коллекций? Ведь не все коллекции одинаково индексируемы!

Здесь на сцену выходит интерфейс IList<T> — универсальный контракт, который требует от коллекции поддерживать работу с элементами по индексу. Если коротко: у вас есть коллекция, которая реализует IList<T>, — значит, можно смело обращаться к её элементам по индексу (как в массиве) и изменять их на лету.

Аналогия:
Вспомните библиотечную карточку: у каждой книги есть свой порядковый номер на полке, и вы всегда можете подойти к "третей по счёту" книге и взять её. Вот так ведёт себя коллекция, поддерживающая IList<T>.

2. Общая структура и методы IList<T>

Интерфейс IList<T> — герой многих коллекций. Он расширяет ICollection<T> (а тот, в свою очередь, IEnumerable<T>, что позволяет проходить по коллекции с помощью циклов), и добавляет самое важное: работу с индексом.

Схема наследования интерфейсов:


IEnumerable<T>
      ▲
      │
ICollection<T>
      ▲
      │
  IList<T>
Наследование интерфейсов коллекций в .NET

Основные члены интерфейса IList<T>

Член Назначение
T this[int index] { get; set; }
Получить или установить элемент по индексу
int IndexOf(T item)
Найти индекс первого вхождения элемента
void Insert(int index, T item)
Вставить элемент в заданную позицию
void RemoveAt(int index)
Удалить элемент по индексу

Все остальные члены, такие как Add, Remove, Clear, Contains, приходят из интерфейса ICollection<T>.

Ключевая фишка: индексатор

Главная "фишка" IList<T> — наличие индексатора. Это такой синтаксический сахар, благодаря которому можно писать:


var myList = new List<int> { 10, 20, 30 };
int secondValue = myList[1]; // Получаем 20
myList[2] = 42;              // Меняем третий элемент

3. Какие коллекции реализуют IList<T>

В стандартной библиотеке .NET многие знакомые структуры поддерживают интерфейс IList<T>. Давайте посмотрим на самые популярные:

Коллекция Индексация Описание
List<T>
Да Динамический массив
T[]
Да Обычные массивы индексируемы
BindingList<T>
Да Используется для data binding
ObservableCollection<T>
Да Список с уведомлениями
Collection<T>
Да Базовый класс для коллекций

Внимание:

LinkedList<T>
и
HashSet<T>
НЕ реализуют IList<T>, потому что у них нет быстрой индексации (да, у LinkedList<T> нет list[5]!).

4. Примеры использования IList<T>

Получение и установка по индексу


using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        IList<string> fruits = new List<string> { "Яблоко", "Банан", "Груша" };

        // Получение второго элемента
        string fruit = fruits[1];
        Console.WriteLine(fruit); // Банан

        // Замена третьего элемента
        fruits[2] = "Апельсин";
        Console.WriteLine(fruits[2]); // Апельсин
    }
}

Вставка и удаление по индексу


fruits.Insert(1, "Киви");    // Вставляем "Киви" на второе место
// Список теперь: "Яблоко", "Киви", "Банан", "Апельсин"

fruits.RemoveAt(0);          // Удаляем первый элемент ("Яблоко")
// Список теперь: "Киви", "Банан", "Апельсин"

Поиск индекса элемента


int index = fruits.IndexOf("Апельсин"); // Вернёт индекс (2) или -1, если не найден
if (index != -1)
    Console.WriteLine("Апельсин находится на позиции: " + index);
else
    Console.WriteLine("Апельсин не найден");

5. Особенности реализации и типичные ошибки

Работая с IList<T>, легко попасть в пару "ловушек", особенно если забыть, что индексация начинается с нуля, а длина коллекции — это актуальное количество элементов.

Например, попытка обратиться к несуществующему элементу:


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

Индексы в C# — это как куры-несушки: начинают с нуля, а не с одного. Если в списке 4 элемента, последний доступный индекс — 3.

Также стоит помнить, что не все реализации IList<T> одинаково быстры. Например, у массива или у List<T> доступ по индексу мгновенный (O(1)), а вот если бы вы реализовали свою коллекцию на базе связного списка и зачем-то навесили на неё IList<T>, операция могла бы стать медленной. Хотя стандартная библиотека так не делает.

И ещё момент: если вы работаете с массивом как с IList<T>, то можете менять элементы, но не менять размер массива. Методы Add, Remove, Insert и т.п. для массива вызовут NotSupportedException.


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

listView[0] = 42; // Работает!
listView.Add(99); // Бросит NotSupportedException

6. Практическое применение и зачем это нужно

В реальных проектах почти каждая вторая коллекция — это что-то, реализующее IList<T>, потому что удобно иметь возможность быстро обращаться к элементам по номеру, изменять их, вставлять и удалять по позиции. Например:

  • Интерфейсные свойства во ViewModel WPF или WinForms, куда байндятся списки UI-элементов.
  • Реализация алгоритмов сортировки, поиска, перестановки, где нужен доступ по индексу.
  • Модули импорта/экспорта данных, которые работают с динамическим списком объектов.

На собеседовании вопрос про отличия IEnumerable<T>, ICollection<T> и IList<T> — классика. Зная, за что отвечает каждый уровень, вы можете уверенно объяснить интервьюеру, почему HashSet<T> не реализует IList<T> (потому что уникальность важнее порядка и индексов!).

2
Задача
C# SELF, 28 уровень, 3 лекция
Недоступна
Работа с методами Insert и IndexOf
Работа с методами Insert и IndexOf
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Ra Уровень 35 Student
4 декабря 2025

Приятная вещь
fruits.ToList().ForEach(Console.WriteLine);