private IEnumerable<string> Tables
{
get
{
yield return "Foo";
yield return "Bar";
}
}
Допустим, я хочу повторить и написать что-то вроде обработки #n of #m.
Есть ли способ узнать значение m без итерации до моей основной итерации?
Я надеюсь, что я ясно дал понять.
c#
.net
ienumerable
sebagomez
источник
источник
Метод
System.Linq.Enumerable.Count
расширенияIEnumerable<T>
имеет следующую реализацию:Таким образом, он пытается привести к объекту, у
ICollection<T>
которого естьCount
свойство, и использует его, если это возможно. В противном случае это повторяется.Поэтому лучше всего использовать
Count()
метод расширения для вашегоIEnumerable<T>
объекта, так как вы получите максимально возможную производительность.источник
ICollection<T>
первую очередь.T
наIEnumerator<T> enumerator = source.GetEnumerator()
, просто вы можете сделать это:IEnumerator enumerator = source.GetEnumerator()
и должны работать!IEnumerable<T>
наследует,IDisposable
что позволяетusing
оператору автоматически утилизировать его.IEnumerable
не. Так что, если вы позвоните вGetEnumerator
любом случае, вы должны закончить сvar d = e as IDisposable; if (d != null) d.Dispose();
Просто добавив дополнительную информацию:
Count()
Расширение не всегда итерации. Рассмотрим Linq to Sql, где счетчик отправляется в базу данных, но вместо возврата всех строк он выдает команду SqlCount()
и возвращает этот результат.Кроме того, компилятор (или среда выполнения) достаточно умен, чтобы вызывать
Count()
метод objects, если он у него есть. Так что это не так, как говорят другие респонденты, быть полностью невежественным и всегда повторять, чтобы подсчитать элементы.Во многих случаях, когда программист просто проверяет,
if( enumerable.Count != 0 )
используяAny()
метод расширения,if( enumerable.Any() )
это гораздо более эффективно при ленивой оценке linq, поскольку он может закорачивать, как только он может определить, есть ли какие-либо элементы. Это также более читабельноисточник
.Count
свойство, поскольку оно всегда знает, какой у него размер. При запросеcollection.Count
нет дополнительных вычислений, он просто возвращает уже известный счетчик. То же самое,Array.length
насколько я знаю. Однако.Any()
получает перечислитель источника с использованиемusing (IEnumerator<TSource> enumerator = source.GetEnumerator())
и возвращает true, если это возможноenumerator.MoveNext()
. Для коллекций:,if(collection.Count > 0)
массивов:if(array.length > 0)
и на перечислимыхif(collection.Any())
.IQueryably<T>
к a,IEnumerable<T>
он не выдаст счетчик sql. Когда я написал это, Linq to Sql был новым; Я думаю, что я просто настаивал на том, чтобы использовать,Any()
потому что для перечислений, коллекций и sql это было намного более эффективно и читабельно (в общем). Спасибо за улучшение ответа.У моего друга есть серия постов в блоге, которые иллюстрируют, почему вы не можете этого сделать. Он создает функцию, которая возвращает IEnumerable, где каждая итерация возвращает следующее простое число, вплоть до
ulong.MaxValue
следующего элемента и не рассчитывается до тех пор, пока вы его не попросите. Быстрый, поп-вопрос: сколько предметов возвращено?Вот посты, но они вроде длинные:
источник
EnumerableFeatures
объект), не требовало бы, чтобы счетчики выполняли какие-либо сложные задачи, но было бы в состоянии задать такие вопросы (наряду с некоторыми другими, такими как «Можете ли вы пообещать всегда возвращайте одну и ту же последовательность элементов »,« Можете ли вы безопасно подвергнуться воздействию кода, который не должен изменять вашу базовую коллекцию »и т. д.), было бы очень полезноset yield options
заявление или нечто подобное для его поддержки. Если правильно спроектировать, онIEnhancedEnumerator
может сделать такие вещи, как LINQ, намного более удобными, исключая множество «защитных»ToArray
илиToList
вызовов, особенно ...Enumerable.Concat
используются для объединения большой коллекции, которая много знает о себе, с маленькой, которая этого не делает.IEnumerable не может рассчитывать без итерации.
При «нормальных» обстоятельствах классы, реализующие IEnumerable или IEnumerable <T>, такие как List <T>, могут реализовать метод Count, возвращая свойство List <T> .Count. Однако метод Count на самом деле не является методом, определенным в интерфейсе IEnumerable <T> или IEnumerable. (Фактически единственным является GetEnumerator.) И это означает, что для него не может быть обеспечена реализация для конкретного класса.
Скорее, Count это метод расширения, определенный для статического класса Enumerable. Это означает, что он может быть вызван для любого экземпляра производного класса IEnumerable <T>, независимо от реализации этого класса. Но это также означает, что он реализован в одном месте, вне любого из этих классов. Что, конечно, означает, что он должен быть реализован таким образом, который полностью независим от внутренних функций этих классов. Единственный способ подсчета - итерация.
источник
В качестве альтернативы вы можете сделать следующее:
источник
Нет не вообще. Одним из аспектов использования перечислимых элементов является то, что фактический набор объектов в перечислении неизвестен (заранее или даже вообще).
источник
Вы можете использовать System.Linq.
Вы получите результат «2».
источник
Выходя за рамки вашего непосредственного вопроса (на который был полностью дан отрицательный ответ), если вы хотите сообщить о прогрессе при обработке перечислимого, вы можете обратиться к моему сообщению в блоге « Отчет о ходе выполнения во время запросов Linq» .
Это позволяет вам сделать это:
источник
Я использовал такой способ внутри метода, чтобы проверить переданный
IEnumberable
контентВнутри такой метод:
источник
bool hasContents = false; if (iEnum != null) foreach (object ob in iEnum) { hasContents = true; ... your code per ob ... }
.Это зависит от того, какая версия .Net и реализация вашего объекта IEnumerable. Microsoft исправила метод IEnumerable.Count для проверки реализации и использует ICollection.Count или ICollection <TSource> .Count, подробности см. Здесь https://connect.microsoft.com/VisualStudio/feedback/details/454130.
И ниже MSIL от Ildasm для System.Core, в котором находится System.Linq.
источник
Вот отличная дискуссия о отложенной оценке и отложенном выполнении . В основном вы должны материализовать список, чтобы получить это значение.
источник
Результат функции IEnumerable.Count () может быть неправильным. Это очень простой пример для тестирования:
Результат должен быть (7,7,3,3), но фактический результат (7,7,3,17)
источник
Лучший способ, который я нашел, - считать, преобразовав его в список.
источник
Я бы предложил вызвать ToList. Да, вы делаете перечисление рано, но у вас все еще есть доступ к вашему списку предметов.
источник
Это может не дать наилучшей производительности, но вы можете использовать LINQ для подсчета элементов в IEnumerable:
источник
Я думаю, что самый простой способ сделать это
Ссылка: system.linq.enumerable
источник
Я пользуюсь
IEnum<string>.ToArray<string>().Length
и все отлично работает.источник
IEnum<string>.Count();
"?Я использую такой код, если у меня есть список строк:
источник