Считать объекты от IEnumerable <T> без итерации?

Это условный оператор, и это не просто кратчайший способ написания операторов if.

Поскольку это выражение, которое возвращает значение, оно может использоваться как часть других выражений.

304
задан Erik Philips 22 February 2018 в 07:23
поделиться

12 ответов

IEnumerable не поддерживает это. Это дизайном. IEnumerable отложенные вычисления использования для получения элементов Вы просите то, перед необходимостью в них.

, Если Вы хотите знать количество объектов, не выполняя итерации по ним, можно использовать ICollection<T>, оно имеет Count свойство.

322
ответ дан ToolmakerSteve 23 November 2019 в 01:21
поделиться

Нет.

Вы видите, что информация, доступная где-нибудь в коде, записали?

Вы могли бы утверждать, что компилятор может "видеть", что существуют только два, но это означало бы, что он должен будет проанализировать каждый метод итератора, ищущий просто что определенный патологический случай. И даже если бы это сделало, как Вы считали бы его, учитывая пределы IEnumerable?

0
ответ дан James Curran 28 July 2019 в 12:37
поделиться

Я предложил бы назвать ToList. Да Вы делаете перечисление рано, но у Вас все еще есть доступ к Вашему списку объектов.

0
ответ дан Jonathan Allen 23 November 2019 в 01:21
поделиться

Нет, не в целом. Одна точка в использовании enumerables - то, что фактический набор объектов в перечислении не известен (заранее, или даже вообще).

8
ответ дан JesperE 23 November 2019 в 01:21
поделиться

У моего друга есть серия сообщений в блоге, которые приводят пример для того, почему Вы не можете сделать этого. Он создает функцию, которые возвращают IEnumerable, куда каждое повторение возвращает следующее простое число, полностью к ulong.MaxValue, и следующий объект не вычисляется, пока Вы не просите его. Быстрый, вопрос о поп: сколько объектов возвращается?

Вот сообщения, но они довольно длинны:

  1. Вне Циклов (обеспечивает начальный класс EnumerableUtility, используемый в других сообщениях)
  2. Приложения Выполняют итерации (Начальное внедрение)
  3. Сумасшедшие Методы Расширения: ToLazyList (Оптимизация производительности)
12
ответ дан Joel Coehoorn 23 November 2019 в 01:21
поделиться

IEnumerable не может рассчитать без итерации.

При "нормальных" обстоятельствах, это было бы возможно для классов, реализовав IEnumerable или IEnumerable< T> такие как List< T> для реализации Метода счета путем возврата List< T> свойство.Count. Однако Метод счета не является на самом деле методом, определенным на IEnumerable< T> или интерфейс IEnumerable. (Единственным то есть, на самом деле, является GetEnumerator.) И это означает, что определенная для класса реализация не может быть обеспечена для него.

Скорее количество это - дополнительный метод, определенный на статическом Счетном классе. Это означает, что это можно назвать на любом экземпляре IEnumerable< T> производный класс, независимо от реализации того класса. Но это также означает, что это реализовано в единственном месте, внешнем к любому из тех классов. Который, конечно, означает, что это должно быть реализовано способом, который абсолютно независим от внутренностей этого класса. Единственное такой способ сделать подсчет через повторение.

10
ответ дан Chris Ammerman 23 November 2019 в 01:21
поделиться

Просто добавив дополнительный некоторая информация:

Count() расширение не всегда выполняет итерации. Рассмотрите Linq к Sql, куда количество переходит к базе данных, но вместо того, чтобы возвратить все строки, это дает команду Sql Count() и возвраты тот результат вместо этого.

Кроме того, компилятор (или время выполнения) достаточно умен, что это назовет объекты Count() метод, если это будет иметь тот. Таким образом, это не , как другие респонденты говорят, будучи абсолютно неосведомленными и всегда выполняющими итерации для подсчета элементов.

Во многих случаях, где программист просто проверяет if( enumerable.Count != 0 ) использование Any(), дополнительный метод, как в if( enumerable.Any() ) намного более эффективен с отложенными вычислениями linq, поскольку это может закоротить, как только это может решить, что существуют любые элементы. Это - также больше читаемое

86
ответ дан c0d3b34n 23 November 2019 в 01:21
поделиться

Here is a great discussion about lazy evaluation and deferred execution. Basically you have to materialize the list to get that value.

2
ответ дан 23 November 2019 в 01:21
поделиться

Going beyond your immediate question (which has been thoroughly answered in the negative), if you're looking to report progress whilst processing an enumerable, you might want to look at my blog post Reporting Progress During Linq Queries.

It lets you do this:

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += (sender, e) =>
      {
          // pretend we have a collection of 
          // items to process
          var items = 1.To(1000);
          items
              .WithProgressReporting(progress => worker.ReportProgress(progress))
              .ForEach(item => Thread.Sleep(10)); // simulate some real work
      };
5
ответ дан 23 November 2019 в 01:21
поделиться

Alternatively you can do the following:

Tables.ToList<string>().Count;
9
ответ дан 23 November 2019 в 01:21
поделиться

The System.Linq.Enumerable.Count extension method on IEnumerable has the following implementation:

ICollection<T> c = source as ICollection<TSource>;
if (c != null)
    return c.Count;

int result = 0;
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
        result++;
}
return result;

So it tries to cast to ICollection, which has a Count property, and uses that if possible. Otherwise it iterates.

So your best bet is to use the Count() extension method on your IEnumerable object, as you will get the best performance possible that way.

208
ответ дан 23 November 2019 в 01:21
поделиться

Результат функции IEnumerable.Count () может быть неверным. Это очень простой пример для тестирования:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;

namespace Test
{
  class Program
  {
    static void Main(string[] args)
    {
      var test = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17 };
      var result = test.Split(7);
      int cnt = 0;

      foreach (IEnumerable<int> chunk in result)
      {
        cnt = chunk.Count();
        Console.WriteLine(cnt);
      }
      cnt = result.Count();
      Console.WriteLine(cnt);
      Console.ReadLine();
    }
  }

  static class LinqExt
  {
    public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int chunkLength)
    {
      if (chunkLength <= 0)
        throw new ArgumentOutOfRangeException("chunkLength", "chunkLength must be greater than 0");

      IEnumerable<T> result = null;
      using (IEnumerator<T> enumerator = source.GetEnumerator())
      {
        while (enumerator.MoveNext())
        {
          result = GetChunk(enumerator, chunkLength);
          yield return result;
        }
      }
    }

    static IEnumerable<T> GetChunk<T>(IEnumerator<T> source, int chunkLength)
    {
      int x = chunkLength;
      do
        yield return source.Current;
      while (--x > 0 && source.MoveNext());
    }
  }
}

Результат должен быть (7,7,3,3), но фактический результат (7,7,3,17)

2
ответ дан 23 November 2019 в 01:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: