Что представляет собой надежный, элегантный, многократно используемый фрагмент кода для определения, является ли IEnumerable пустым, в .NET? - PullRequest
9 голосов
/ 23 сентября 2008

Я пытаюсь найти наиболее многократно используемый, но элегантный кусок кода, который можно определить, если IEnumerable. В идеале это должна быть функция, которую я могу вызывать абсолютно в любое время, когда мне нужно сказать, пуст ли IEnumerable.

Хотя я разработал ответ для .NET 3.5, который до сих пор работал для меня, моя текущая мысль заключается в том, что нет идеального ответа, поскольку IEnumerable технически может инкапсулировать коллекцию (или очередь итераторов), которая изменяет лежащие в основе результаты во время итерации, что может вызвать проблемы. Однако это также будет препятствием для реализации IEnumerable.Count (), и это не помешало MS предоставить его.

Так что я решил поставить его на SO, чтобы узнать, есть ли у кого-то лучше, и в случае, если кто-то найдет его полезным.

Редактировать: Ничего себе, я не могу поверить, что я не знал о IEnumerable.Any. Я знал, что это существует, но никогда не удосужился проверить, что он сделал. Пусть это будет уроком. Прочитайте документацию. Тот факт, что имя метода не означает, что он делает то, что вы хотите, не означает, что он не делает то, что вы хотите.

Ответы [ 5 ]

22 голосов
/ 23 сентября 2008
!enumerable.Any()

Будет пытаться захватить только первый элемент.

Чтобы раскрыть, как / почему это работает, любой определяет, соответствует ли какой-либо из компонентов IEnumerable заданной функции, если ни один не задан, тогда любой компонент завершится успешно, то есть функция вернет true, если элемент существует в перечисляемом.

2 голосов
/ 23 сентября 2008

Вы правы, что нет идеального ответа. IEnumerable поддерживает только итерацию и не гарантирует повторяемость перечисления. Вы не можете выяснить, содержит ли перечисление элементы, не вызывая MoveNext хотя бы один раз, и как только вы это сделаете, вы не сможете гарантировать, что сможете повторно использовать перечисление: IEnumerable.Reset может выдать исключение NotSupportedException. От http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx:

"Метод Reset предназначен для взаимодействия COM. Его не обязательно нужно реализовывать; вместо этого разработчик может просто вызвать исключение NotSupportedException."

Методы расширения, такие как IEnumerable .Count и IEnumerable . Любая необходимость вызывать MoveNext под прикрытием. Полезные обертки, но не избегайте того факта, что в (редких) случаях, когда перечисление не поддерживает сброс, вы можете столкнуться с проблемой.

2 голосов
/ 23 сентября 2008

Для .net 1/2:

IEnumerator e;
try
{
   e = enumerable.GetEnumerator();
   return e.MoveNext();
}
finally
{ 
    if (e is IDisposable)
        e.Dispose();
}

Или с дженериками:

using (IEnumerator<T> e = enumerable.GetEnumerator())
{
    return e.MoveNext();
}
0 голосов
/ 13 марта 2009

Первый метод имеет простую реализацию метода расширения Empty: http://signum.codeplex.com/SourceControl/changeset/view/25903#510468

0 голосов
/ 23 сентября 2008

При использовании любого из этих методов следует помнить, что не все перечисления можно откатить, например, все реализации System.Data.IDataReader могут выполняться только один раз.

В этих случаях у вас нет затрат в цикле foreach, при условии, что вы учитываете тот факт, что он может даже не цикл один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...