TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #1827 1.46K
День 1491. #ЗаметкиНаПолях
Какой Интерфейс Коллекции Использовать? Окончание
Начало
Продолжение

3. IEnumerable - тоже дырявая абстракция
В предыдущем посте мы выяснили, что нужно использовать IReadOnlyList в качестве возвращаемого типа коллекции. Но почему так много известных библиотек вместо этого используют IEnumerable?

Одна из причин — ленивая оценка. В .NET BCL большинство инструкций LINQ обрабатываются лениво при работе с IEnumerable:
var numbers = new int[] { 1, 2, 3 };
var r1 = numbers.Where(x => x > 1);
var r2 = r1.Select(x => x + 1);
int result = r2.Sum();

Здесь выполнение 2 и 3 строк откладывается до строки 4, где вызывается Sum. Если нужно поддерживать ленивую оценку, используйте IEnumerable, иначе IReadOnlyList.

IEnumerable и ORM
Обратите внимание, что ленивое вычисление также приводит к тому, что IEnumerable в некоторых сценариях является дырявой абстракцией:
// Student repository
public IEnumerable<Student> GetAll()
{
using SchoolContext ctx = new();
return ctx.Set<Student>();
}

// контроллер
public IEnumerable<StudentDto> Get()
{
var students = _repo.GetAll();
var dtos = students.Select(MapToDto);
return dtod.ToList();
}

Код в контроллере выполняется только когда вызывается ToList. Если к этому моменту DbContext уже утилизирован, мы получим исключение. Это ещё один пример дырявой абстракции: EF Core требует от вас знать, открыто ли соединение с БД во время оценки IEnumerable. Хотя это не такая уж проблема, поскольку наличие постоянного DbContext является разумным предположением в большинстве веб-приложений. У вас почти всегда будет активный экземпляр DbContext на протяжении всей бизнес-операции.

IEnumerable без ORM
Реализации IEnumerable часто действуют как дырявые абстракции даже в сценариях без ORM. Например, BlockingCollection реализует IEnumerable таким образом, что он блокирует вызывающий поток в методе MoveNext() до тех пор, пока другой поток не добавит элемент в эту коллекцию. А при реализации «бесконечной» коллекции через yield return вызов ToList на такой коллекции приведёт к зависанию программы в бесконечном цикле. Технически это не дырявая абстракция, т.е. IEnumerable не обещает конечность коллекции, но на практике большинство программистов ожидают от IEnumerable определённого поведения. Можно сказать, что IEnumerable имеет неявный контракт, на который полагаются большинство программистов, и некоторые реализации IEnumerable нарушают его.

IEnumerable в разработке библиотек
Если вы разрабатываете библиотеку для публичного использования, лучше максимально ограничить её публичный API, чтобы дать себе возможность обновлять его. Это включает как количество публичных методов, так и типы, возвращаемые этими методами. Тогда предпочтительнее возвращать IEnumerable вместо IReadOnlyList. Это позволит изменить внутреннюю реализацию, например, List<T> на LinkedList<T>, не нарушая обратной совместимости.

Итого
- Используйте IEnumerable для аргументов как наиболее универсальный тип из возможных.
- Используйте IReadOnlyList для возвращаемых значений как наиболее конкретный возможный тип.
- IQueryable — дырявая абстракция, потому что она требует, чтобы вы знали, какие выражения LINQ может понять ORM.
- IList и Array не подходят, потому что они изменяемы.
- Имейте в виду, что некоторые реализации IEnumerable также являются дырявыми абстракциями.

Источник: https://enterprisecraftsmanship.com/posts/which-collection-interface-to-use/
  • 👍 16
More from @netdeveloperdiary
  1. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  2. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  3. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  4. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  5. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  6. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →