В чём разница между кешем (cache) и словарём (dictionary) как структурами данных?

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

Ответ

Хотя оба хранят данные по ключу, их цели, поведение и гарантии кардинально отличаются.

Словарь (Dictionary/Hash Map)

  • Основная цель: Структура данных для долгосрочного хранения пар ключ-значение с гарантированно быстрым доступом O(1) в среднем случае.
  • Управление данными: Ручное. Разработчик явно добавляет и удаляет элементы. Словарь хранит всё, что в него положили, пока это не будет удалено явно или пока жив сам словарь.
  • Пример использования в C#:
    var userCache = new Dictionary<int, User>(); // Это НЕ кеш, а просто хранилище.
    userCache.Add(user.Id, user); // Добавили
    if (userCache.TryGetValue(123, out var cachedUser)) { /* ... */ }
    userCache.Remove(123); // Удалили явно

Кеш (Cache)

  • Основная цель: Промежуточный буфер для ускорения доступа к медленным или дорогим данным (БД, внешний API, диск) с автоматическим управлением жизненным циклом записей.
  • Управление данными: Автоматическое по политикам. Кеш сам решает, какие данные удалить, когда он заполнен или когда данные устарели.
  • Ключевые политики вытеснения (Eviction Policies):
    • По времени (TTL - Time To Live): Запись удаляется через фиксированное время после создания или последнего доступа.
    • По размеру (Capacity): При заполнении кеша удаляются наименее полезные записи.
      • LRU (Least Recently Used): Вытесняет давно неиспользуемые.
      • LFU (Least Frequently Used): Вытесняет реже всего используемые.
  • Пример использования IMemoryCache в ASP.NET Core:

    // Регистрация
    services.AddMemoryCache();
    
    // Использование
    public class UserService
    {
        private readonly IMemoryCache _cache;
        public User GetUser(int id)
        {
            // Попытка получить из кеша. Если нет — вызов медленного метода и сохранение.
            return _cache.GetOrCreate(id, entry =>
            {
                entry.SlidingExpiration = TimeSpan.FromMinutes(10); // Удалится, если не обращались 10 мин.
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1); // Удалится через час в любом случае.
                return _dbContext.Users.Find(id); // Дорогой вызов к БД
            });
        }
    }
Сравнительная таблица: Характеристика Словарь (Dictionary) Кеш (Cache)
Гарантия хранения Данные хранятся, пока не удалены явно. Данные могут быть удалены в любой момент автоматически.
Управление памятью Ручное. Риск утечки, если забыть удалить. Автоматическое по политикам (TTL, размер).
Семантика Структура данных. Архитектурный паттерн/компонент.
Типичная реализация Хэш-таблица. Часто использует словарь внутри + логика вытеснения.

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