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

StackOverflow https://stackoverflow.com/questions/117355

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

Это было полезно?

Решение

!enumerable.Any()

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

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

Другие советы

Для .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();
}

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top