В чем разница в получении данных по индексу из списка (List) и по ключу из словаря (Dictionary) в C#?

«В чем разница в получении данных по индексу из списка (List) и по ключу из словаря (Dictionary) в C#?» — вопрос из категории Алгоритмы и структуры данных, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Разница заключается в механизме доступа и его алгоритмической сложности, что напрямую влияет на производительность.

Список (List<T>)

  • Доступ по индексу: T item = myList[index];
  • Сложность: O(1) - константное время.
  • Причина: Список внутри — это динамический массив. Доступ по индексу — это просто вычисление смещения в памяти: адрес_начала + index * размер_элемента. Это одна операция.
  • Когда использовать: Когда важен порядок элементов, и вы работаете с индексами (например, итерация в for цикле, доступ к известной позиции).

Словарь (Dictionary<TKey, TValue>)

  • Доступ по ключу: TValue value = myDict[key];
  • Сложность: В среднем O(1), в худшем случае O(n).
  • Причина: Словарь внутри — это хэш-таблица.
    1. Вычисляется хэш-код ключа (key.GetHashCode()).
    2. По хэш-коду определяется корзина (bucket), где должна храниться пара ключ-значение.
    3. Внутри корзины может быть несколько элементов (при коллизиях). Происходит поиск по ключу с использованием Equals. При хорошем распределении хэшей и количестве элементов, близкому к количеству корзин, поиск почти мгновенный.
  • Когда использовать: Когда нужен быстрый поиск, обновление или проверка существования элемента по уникальному ключу (ID, имя пользователя и т.д.).

Сравнительный пример:

// List: Быстрый доступ по известному индексу
var usersList = new List<string> { "Alice", "Bob", "Charlie" };
string userAtIndex1 = usersList[1]; // "Bob" - моментально

// Dictionary: Быстрый доступ по смыслу данных
var usersDict = new Dictionary<int, string>
{
    { 101, "Alice" },
    { 102, "Bob" },
    { 103, "Charlie" }
};
string userWithId102 = usersDict[102]; // "Bob" - моментально по ID

// Неэффективно для словаря: попытка найти значение перебором (O(n))
foreach (var kvp in usersDict)
{
    if (kvp.Value == "Bob") { /* Медленно! */ }
}

Вывод: Используйте List для работы с индексами и порядком, Dictionary — для работы с ключами и быстрого поиска.