Разница между IEnumerable Count() и Length


каковы основные различия между IEnumerableCount() и Length?

3 53

3 ответа:

по телефону рассчитывать на IEnumerable<T> Я предполагаю, что вы имеете в виду метод расширения Count on System.Linq.Enumerable. Length - это не метод IEnumerable<T> но скорее свойство для типов массивов в .Net, таких как int[].

разница в производительности. ЭлементLength свойство гарантированно будет операцией O(1). Сложность Count метод расширения зависит от типа времени выполнения объекта. Он попытается привести к нескольким типам, которые поддерживают O (1) length lookup как ICollection<T> через a Count собственность. Если ни один из них не доступен, то он будет перечислять все элементы и подсчитывать их, которые имеют сложность O(N).

int[] list = CreateSomeList();
Console.WriteLine(list.Length);  // O(1)
IEnumerable<int> e1 = list;
Console.WriteLine(e1.Count()); // O(1) 
IEnumerable<int> e2 = list.Where(x => x <> 42);
Console.WriteLine(e2.Count()); // O(N)

значение e2 реализуется как итератор C#, который не поддерживает подсчет O(1) и, следовательно, метод Count необходимо перечислить всю коллекцию, чтобы определить ее длину.

маленькое дополнение к Джон Скиткомментарий.

здесь код Count() метод расширения:

.NET 3:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> is2 = source as ICollection<TSource>;
    if (is2 != null)
    {
        return is2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}

.NET 4:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> is2 = source as ICollection<TSource>;
    if (is2 != null)
    {
        return is2.Count;
    }
    ICollection is3 = source as ICollection;
    if (is3 != null)
    {
        return is3.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}
  • длина-это фиксированное свойство, например, одномерного массива или строки. Таким образом, никогда не требуется операция подсчета (многомерные массивы имеют размер всех умноженных измерений). O (1) операция здесь означает, что время извлечения всегда одно и то же, независимо от того, сколько элементов есть. Линейный поиск был бы(в противоположность этому) O (n).

  • свойство Count в ICollections (List и List, например) может измениться, поэтому оно имеет либо для обновления при операциях добавления/удаления или при запросе Count после изменения коллекции. Зависит от реализации объекта.

  • метод Count () LINQ в основном повторяется каждый раз, когда он вызывается (за исключением случаев, когда объект является типом ICollection, а затем ICollection.Свойство Count запрашивается).

обратите внимание, что IEnumerables часто не являются уже определенными коллекциями объектов (например, списки, массивы, хэш-таблицы и т. д.), но ссылка на фоновые операции, которые генерируют результаты всякий раз, когда они запрашиваются (называется отложенное выполнение).

как правило, у вас есть SQL, как LINQ заявление, как это (типичное применение отложенного выполнения):

IEnumerable<Person> deptLeaders = 
   from p in persons
   join d in departments
      on p.ID equals d.LeaderID
   orderby p.LastName, p.FirstName
   select p;

тогда есть такой код:

if (deptLeaders.Count() > 0)
{
   ReportNumberOfDeptLeaders(deptLeaders.Count());
   if (deptLeaders.Count() > 20)
      WarnTooManyDepartmentLeaders(deptLeaders.Count());
}

таким образом, когда выдается предупреждение для слишком многих руководителей отделов, .NET проходит четыре раза через лиц, проверяет их против руководителей отделов, сортирует их по имени, а затем подсчитывает результирующие объекты.

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