В чем основные различия между IEnumerable
Count()
и Length
?
Разница между IEnumerable Count () и длиной
Ответы (3)
Вызывая Count на IEnumerable<T>
, я предполагаю, что вы имеете в виду метод расширения Count
на System.Linq.Enumerable
. Length
- это не метод IEnumerable<T>
, а свойство типов массивов в .Net, таких как int[]
.
Разница в производительности. СвойствоLength
гарантированно является операцией O (1). Сложность метода расширения Count
зависит от типа среды выполнения объекта. Он попытается выполнить приведение к нескольким типам, которые поддерживают поиск длины O (1), например ICollection<T>
, через свойство 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
должен перечислить всю коллекцию, чтобы определить ее длину.
List<T>
не имеет свойства Length - у него есть свойство Count. Однако у массивов есть Length
. Count
указан в ICollection
и ICollection<T>
(который IList<T>
расширяет).
- person Jon Skeet; 26.03.2010
string[]
с, скажем, 5-10 элементами ... вы бы предложили Array.Length
для повышения производительности?
- person one.beat.consumer; 18.04.2012
Count()
, поскольку массив будет реализовывать ICollection<T>
, но это менее эффективно, чем использование Length
напрямую. Если вы уже знаете, что это массив, я бы использовал Length
не для повышения эффективности, а потому, что я считаю его более идиоматическим. Точно так же я бы использовал свойство Count
для всего, что имеет тип времени компиляции ICollection<T>
. Я бы вызвал Count()
, когда выражение времени компиляции имеет тип IEnumerable<T>
, даже если я знаю, что это действительно скрытый массив.
- person Jon Skeet; 18.04.2012
System.Array
был гораздо более базовым классом (похожим на object
); но после проверки MSDN я вижу, что он реализует несколько интерфейсов, связанных с коллекциями. Я веб-программист, поэтому сначала Count имел более семантический смысл (например, header
против div
в HTML), но я понимаю вашу точку зрения, поскольку это явно string[]
во время компиляции Length
имеет больше смысла.
- person one.beat.consumer; 18.04.2012
while(list.Count() > 0)
немного логики с действиями добавления / удаления.
- person Johnny_D; 30.04.2014
Небольшое дополнение к комментарию Джона Скита.
Вот исходный код метода расширения 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;
}
ICollection
. (Поскольку это также имеет свойство Count
.)
- person Jon Skeet; 26.03.2010
use
, чтобы получить Error
класс, который использует этот метод? Я не могу найти его нигде в MSDN, кроме документации JScript.
- person Moshe Katz; 11.06.2012
Длина - это фиксированное свойство, например одномерного массива или строки. Таким образом, никогда не требуется операция подсчета (многомерные массивы имеют размер, умноженный на все измерения). Операция O (1) здесь означает, что время поиска всегда одинаково, независимо от количества элементов. Линейный поиск (в отличие от этого) будет O (n).
Свойство Count в ICollections (например, List и List ‹T›) может изменяться, поэтому его необходимо обновлять либо при операциях добавления / удаления, либо при запросе Count после изменения коллекции. Зависит от реализации объекта.
Метод Count () LINQ в основном выполняет итерацию КАЖДЫЙ РАЗ, когда он вызывается (кроме случаев, когда объект является типом ICollection, тогда запрашивается свойство ICollection.Count).
Обратите внимание, что IEnumerable часто не являются уже определенными коллекциями объектов (например, списками, массивами, хэш-таблицами и т. Д.), Но связаны с фоновыми операциями, которые генерируют результаты всякий раз, когда они запрашиваются (так называемое отложенное выполнение).
Обычно у вас есть такой 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 ЧЕТЫРЕ РАЗ просматривает людей, сравнивает их с руководителями отделов, сортирует их по именам и затем подсчитывает объекты результатов.
И это только тогда, когда люди и отделы представляют собой предварительно установленные наборы значений, а не сами запросы.
.Count() > 0
- это то же самое, что .Any()
.
- person jedmao; 10.01.2012
.Any()
не будет эффективнее, чем .Count() > 0
? Кстати, Resharper всегда жалуется на .Count() > 0
. Вот почему я говорю об этом с уверенностью.
- person jedmao; 09.02.2012