Вы можете использовать методы расширения, такие как Any () или Count (). Count () является более дорогостоящим, чем Any (), так как он должен выполнить все перечисление, как указали другие.
Но в случае ленивой оценки (например, метод, который использует доходность), любой из них может быть дорогостоящим. Например, в следующей реализации IEnumerable
каждый вызов Any или Count повлечет за собой стоимость нового обращения к базе данных:
IEnumerable<MyObject> GetMyObjects(...)
{
using(IDbConnection connection = ...)
{
using(IDataReader reader = ...)
{
while(reader.Read())
{
yield return GetMyObjectFromReader(reader);
}
}
}
}
Я думаю, что мораль такова:
Если у вас есть только IEnumerable<T>
, и вы хотите сделать больше, чем просто перечислить его (например, использовать Count или Any), то сначала рассмотрите преобразование его в List (метод расширения ToList). Таким образом, вы гарантируете перечисление только один раз.
Если вы разрабатываете API, который возвращает коллекцию, рассмотрите возможность возврата ICollection<T>
(или даже IList<T>
), а не IEnumerable<T>
, как многие рекомендуют. Тем самым вы укрепляете свой контракт, чтобы гарантировать отсутствие отложенной оценки (и, следовательно, отсутствие многократной оценки).
Обратите внимание, я говорю, что вы должны рассмотреть возврат коллекции, а не всегда вернуть коллекцию. Как всегда, есть компромиссы, как видно из комментариев ниже.
@ KeithS считает, что вы никогда не должны уступать DataReader, и хотя я никогда не говорю никогда, я бы сказал, что в целом это здравый совет, что уровень доступа к данным должен возвращать ICollection<T>
, а не ленивый IEnumerable<T>
, по причинам, которые KeithS приводит в своем комментарии.
@ Bear Monkey отмечает, что создание экземпляра List может оказаться дорогостоящим в приведенном выше примере, если база данных возвращает большое количество записей. Это также верно, и в некоторых (возможно, редких) случаях может быть целесообразно игнорировать совет @ KeithS и возвращать перечисление с ленивой оценкой, если потребитель делает что-то не слишком трудоемкое (например, генерирует некоторые агрегированные значения).