Как стать автором
Обновить

Проверки на пустые перечисления

.NET
Перевод
Автор оригинала: Phil Haack
Недавно, во время разбора кода одной программы я заметил метод, который выглядел примерно так:

public void Foo<T>(IEnumerable<T> items)
{
if(items == null || items.Count() == 0)
{
// Оповестить о пустом перечислении
}
}



Метод принимает дженерик-перечисление и проверяет, пустое ли оно. Видите ли вы тут потенциальную проблему? Я намекну, проблема в этой строчке:

items.Count() == 0


И в чем же тут проблема? Проблема в том, что эта строчка может оказаться очень неэффективной.

Если вызвать наш метод, передав ему перечисление, которое не реализует ICollection<T> (например, IQueryable результат запроса к Entity Framework или LINQ to SQL), метод Count() будет перебирать всю коллекцию ради выполнения этой проверки.

В случае, когда перечисление реализует ICollection<T>, все в порядке. Метод Count() оптимизирован для таких случаев и проверит свойство Count.

Если говорить человеческим языком, то наша строчка отвечает на вопрос «Количество в перечислении равно нулю?». Но это вовсе не то, что нас интересует. На самом деле нам нужно ответить на вопрос «Есть ли в перечислении хотя бы один элемент?».

Если подойти к задаче таким образом, то решение станет очевидным: использовать расширение Any из пространства имен System.Linq.

public void Foo<T>(IEnumerable<T> items)
{
if(items == null || !items.Any())
{
// Оповестить о пустом перечислении
}
}



Красота такого метода в том, что ему достаточно вызвать MoveNext интерфейса IEnumerable только один раз! У вас может быть бесконечно большое перечисление, но Any вернет результат немедленно.

Еще лучше было бы, поскольку такая проверка используется постоянно, подумать над реализацией своего простого метода-расширения:

public static bool IsNullOrEmpty<T>(this IEnumerable<T> items)
{
return items == null || !items.Any();
}



Теперь, с таким методом, исходный код выглядит еще проще:

public void Foo<T>(IEnumerable<T> items)
{
if(items.IsNullOrEmpty())
{
// Оповестить о пустом перечислении
}
}



С таким методом-расширением в своем инструментарии, вы никогда снова не проверите пустоту перечисления неэффективно.
Теги:.netenumerablelinq2sqlentity frameworkоптимизация программ
Хабы: .NET
Всего голосов 128: ↑91 и ↓37 +54
Просмотры8.9K

Похожие публикации

C# .net Developer
от 90 000 до 180 000 ₽АЛМАЗМоскваМожно удаленно
Разработчик C# (.NET)
от 150 000 до 250 000 ₽Action techМоскваМожно удаленно
Senior .Net Engineer (C#)
до 230 000 ₽ItivitiСанкт-Петербург
Инженер-программист
от 50 000 до 100 000 ₽ГК «Мой Рейс»МоскваМожно удаленно
.Net разработчик
от 150 000 ₽ArtezioСанкт-Петербург

Лучшие публикации за сутки