Какой метод работает лучше: .Any () vs .Count () ›0?

в пространстве имен System.Linq теперь мы можем расширить наш IEnumerable, чтобы иметь Any () и Count () методы расширения.

Недавно мне сказали, что если я хочу проверить, что коллекция содержит 1 или более элементов внутри, я должен использовать метод расширения .Any() вместо метода расширения .Count() > 0, потому что метод расширения .Count() должен перебирать все элементы.

Во-вторых, у некоторых коллекций есть свойство (не метод расширения), равное Count или Length. Было бы лучше использовать их вместо .Any() или .Count()?

да / нет?


person Pure.Krome    schedule 20.11.2008    source источник
comment
Лучше использовать Any () для перечислений и рассчитывать на коллекции. Если кто-то чувствует, что написание «(somecollection.Count› 0) »запутает или вызовет проблемы с читабельностью, лучше напишите его как метод расширения, назовите его Any (). Тогда все остались довольны. С точки зрения производительности и удобочитаемости. Так что весь ваш код будет согласован и индивидуальному разработчику в вашем проекте не нужно беспокоиться о выборе Count vs Any.   -  person Mahesh Bongani    schedule 06.06.2019
comment
Вы видели Count () ›0 vs Any (), но видели ли вы Distinct (). Count ()› 1 vs Distinct (). Skip (1) .Any ()? Последнее определенно намного быстрее для большого количества элементов, где Count на самом деле должен перебирать весь набор, чтобы получить счет. Skip (1) .Any () избегает полного перечисления. 100 000 итераций проверки для массива строк из 1000 элементов с 1 символьной строкой, которая выполняется примерно за 4000 мс для Count () ›1, выполняется всего за 20 мс для Skip (1). Any ().   -  person Triynko    schedule 13.06.2020


Ответы (10)


Если вы начинаете с чего-то, что имеет .Length или .Count (например, ICollection<T>, IList<T>, List<T> и т. Д.), То это будет самый быстрый вариант, поскольку ему не нужно проходить последовательность _6 _ / _ 7 _ / _ 8_, требуемую Any() для проверки непустой IEnumerable<T> последовательности.

Всего лишь для IEnumerable<T>, тогда Any() будет в целом быстрее, так как нужно учитывать только одну итерацию. Однако обратите внимание, что реализация Count() LINQ-to-Objects действительно проверяет ICollection<T> (с использованием .Count в качестве оптимизации), поэтому, если ваш базовый источник данных напрямую является списком / коллекцией, не будет будет огромная разница. Не спрашивайте меня, почему он не использует неуниверсальный _16 _...

Конечно, если вы использовали LINQ для фильтрации и т. Д. (Where и т. Д.), У вас будет последовательность, основанная на блоках итератора, и поэтому такая ICollection<T> оптимизация бесполезна.

Обычно с IEnumerable<T>: придерживайтесь Any() ;-p

person Marc Gravell    schedule 20.11.2008
comment
Марк: ICollection ‹T› на самом деле не является производным от ICollection. Я тоже был удивлен, но Reflector не врет. - person Bryan Watts; 26.11.2008
comment
Не проверяет ли реализация Any () интерфейс ICollection, а затем проверяет свойство Count? - person derigel; 29.09.2009
comment
Нет (проверив отражатель) - person Marc Gravell; 30.09.2009
comment
Я думаю, что есть еще одна причина для использования Any () в большинстве случаев. Он сигнализирует о точных намерениях разработчика. Если вам не интересно знать количество элементов, а только если они есть, то somecollection.Any () проще и понятнее, чем somecollection.Count ›0 - person T.J.Kjaer; 22.11.2010
comment
@MarcGravell У вас есть какие-либо комментарии к примеру Entity Framework, который я только что опубликовал? - person nikib3ro; 15.06.2012
comment
@ kape123, как уже отмечал другой пользователь: потребуется увидеть SQL - person Marc Gravell; 15.06.2012
comment
@MarcGravell Добавлено ... постарайтесь не слишком много смотреть на сгенерированный SQL, так как ваши глаза могут выскочить;) - person nikib3ro; 15.06.2012
comment
@huttelihut - Сколько вы знаете разработчиков, которые искренне сбиты с толку заявлением (somecollection.Count > 0)? Был ли трудным для понимания весь наш код до появления метода LINQ .Any ()? - person CraigTP; 07.11.2013
comment
Еще лучшим вариантом может быть создание собственного метода расширения IsEmpty (), который пытается выполнить приведение к коллекции или массиву (для использования Count или Length) и возвращается к Any (). Оптимизирован для всех случаев и проясняет намерения. - person Eldritch Conundrum; 19.12.2013
comment
@EldritchConundrum Это звучит как лучший вариант, я считаю - person Coops; 08.01.2014
comment
Вы: Не спрашивайте меня, почему он не использует неуниверсальный ICollection. В очень редких случаях тип, который реализовал общий IEnumerable<>, будет реализовывать только неуниверсальный ICollection. Проверять и ICollection<>, и ICollection было бы слишком много. - person Jeppe Stig Nielsen; 04.03.2014
comment
Я думаю, что совет @Mark вошел в Resharper, он говорит вам заменить Count() на Any() (я отказался прислушиваться к его совету, я предпочитаю Count() == 0, чем !Any()) - person Chris S; 24.04.2014
comment
@JeppeStigNielsen: Если экземпляр List<Cat> передается методу, ожидающему IEnumerable<Animal>, будет ли какой-либо интерфейс, реализующий Count, более доступным, чем неуниверсальный ICollection? Обратите внимание, что List<Cat> не будет реализовывать IList<Animal>, и код, который получает IEnumerable<Animal>, скорее всего, ничего не будет знать о классе Cat или любых универсальных шаблонах, связанных с этим типом. - person supercat; 30.04.2014
comment
@supercat Очень хорошее наблюдение. Вы абсолютно правы. Это из-за ковариации IEnumerable<out T>. Расширение Linq Count() будет проверять только ICollection<TSource>, в вашем примере это ICollection<Animal>. Этот интерфейс не реализован, поскольку ICollection<> не может быть ковариантным (он содержит такие методы, как bool Remove(T item)). Linq Count() не обнаруживает, что ICollection<Cat> действительно реализован. - person Jeppe Stig Nielsen; 30.04.2014
comment
@supercat Я проверил это на себе, создав class MyColl<T> : ICollection<T>, где я пишу сообщение, если вызывается свойство Count или GetEnumerator() метод. Затем (new MyGenericColl<string>()).Count(); использует ярлык; (new MyGenericColl<string>()).Count<object>(); нет. - person Jeppe Stig Nielsen; 30.04.2014
comment
@supercat Из-за вашего комментария я обновлю свой вопрос в другом месте на SO. - person Jeppe Stig Nielsen; 30.04.2014
comment
@CraigTP Нет, huttelihut говорит совсем не об этом. Дело в том, что когда есть доступный вариант, который явно передает, что делает разработчик, его следует использовать (при условии, что в этом нет никаких практических недостатков). - person JLRishe; 15.07.2014
comment
@JLRishe - Я по-прежнему считаю, что someCollection.Count > 0 так же ясно, как someCollection.Any(), и имеет дополнительное преимущество в виде большей производительности и отсутствия необходимости в LINQ. Конечно, это очень простой случай, и другие конструкции, использующие операторы LINQ, передадут намерения разработчиков намного яснее, чем эквивалентный вариант, не связанный с LINQ. - person CraigTP; 15.07.2014
comment
@CraigTP, не путайте свойство Count с методом Count(). Две разные вещи, и вопрос касался метода, а не свойства ... - person walther; 20.10.2014
comment
@walther, свойства Count и Length действительно упоминались в вопросе, а также в этом ответе как самый быстрый вариант, если это возможно. Я также согласен с тем, что они, вероятно, так же понятны разработчикам, как Any(). Поклянись, мама. - person st3inn; 13.01.2015
comment
@MarcGravell, После декомпиляции исходного кода я заметил, что оптимизация в Count не верна для Any, знаете почему? - person gdoron is supporting Monica; 19.05.2015

Примечание. Я написал этот ответ, когда еще существовала Entity Framework 4. Суть этого ответа заключалась не в том, чтобы вдаваться в тривиальное тестирование производительности .Any() vs .Count(). Дело было в том, чтобы сигнализировать о том, что EF далек от совершенства. Более новые версии лучше ... но если у вас есть часть кода, который медленный и использует EF, протестируйте с прямым TSQL и сравните производительность, а не полагайтесь на предположения (что .Any() ВСЕГДА быстрее, чем .Count() > 0).


Хотя я согласен с наиболее одобренными ответами и комментариями - особенно в отношении того, что Any сигнализирует о намерении разработчика лучше, чем Count() > 0, - у меня была ситуация, в которой Count на SQL Server на порядок быстрее (EntityFramework 4).

Вот запрос с Any, что исключение тайм-аута w (для ~ 200000 записей):

con = db.Contacts.
    Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
        && !a.NewsletterLogs.Any(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr)
    ).OrderBy(a => a.ContactId).
    Skip(position - 1).
    Take(1).FirstOrDefault();

Count версия выполняется за миллисекунды:

con = db.Contacts.
    Where(a => a.CompanyId == companyId && a.ContactStatusId <= (int) Const.ContactStatusEnum.Reactivated
        && a.NewsletterLogs.Count(b => b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr) == 0
    ).OrderBy(a => a.ContactId).
    Skip(position - 1).
    Take(1).FirstOrDefault();

Мне нужно найти способ увидеть, какой именно SQL выдают оба LINQ, но очевидно, что в некоторых случаях существует огромная разница в производительности между Count и Any, и, к сожалению, кажется, что вы не можете просто придерживаться Any во всех случаях.

РЕДАКТИРОВАТЬ: вот сгенерированные SQL-запросы. Красавицы как видите;)

ANY:

exec sp_executesql N'SELECT TOP (1) 
[Project2].[ContactId] AS [ContactId], 
[Project2].[CompanyId] AS [CompanyId], 
[Project2].[ContactName] AS [ContactName], 
[Project2].[FullName] AS [FullName], 
[Project2].[ContactStatusId] AS [ContactStatusId], 
[Project2].[Created] AS [Created]
FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created], row_number() OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number]
    FROM ( SELECT 
        [Extent1].[ContactId] AS [ContactId], 
        [Extent1].[CompanyId] AS [CompanyId], 
        [Extent1].[ContactName] AS [ContactName], 
        [Extent1].[FullName] AS [FullName], 
        [Extent1].[ContactStatusId] AS [ContactStatusId], 
        [Extent1].[Created] AS [Created]
        FROM [dbo].[Contact] AS [Extent1]
        WHERE ([Extent1].[CompanyId] = @p__linq__0) AND ([Extent1].[ContactStatusId] <= 3) AND ( NOT EXISTS (SELECT 
            1 AS [C1]
            FROM [dbo].[NewsletterLog] AS [Extent2]
            WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId])
        ))
    )  AS [Project2]
)  AS [Project2]
WHERE [Project2].[row_number] > 99
ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4

COUNT:

exec sp_executesql N'SELECT TOP (1) 
[Project2].[ContactId] AS [ContactId], 
[Project2].[CompanyId] AS [CompanyId], 
[Project2].[ContactName] AS [ContactName], 
[Project2].[FullName] AS [FullName], 
[Project2].[ContactStatusId] AS [ContactStatusId], 
[Project2].[Created] AS [Created]
FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created], row_number() OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number]
    FROM ( SELECT 
        [Project1].[ContactId] AS [ContactId], 
        [Project1].[CompanyId] AS [CompanyId], 
        [Project1].[ContactName] AS [ContactName], 
        [Project1].[FullName] AS [FullName], 
        [Project1].[ContactStatusId] AS [ContactStatusId], 
        [Project1].[Created] AS [Created]
        FROM ( SELECT 
            [Extent1].[ContactId] AS [ContactId], 
            [Extent1].[CompanyId] AS [CompanyId], 
            [Extent1].[ContactName] AS [ContactName], 
            [Extent1].[FullName] AS [FullName], 
            [Extent1].[ContactStatusId] AS [ContactStatusId], 
            [Extent1].[Created] AS [Created], 
            (SELECT 
                COUNT(1) AS [A1]
                FROM [dbo].[NewsletterLog] AS [Extent2]
                WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId])) AS [C1]
            FROM [dbo].[Contact] AS [Extent1]
        )  AS [Project1]
        WHERE ([Project1].[CompanyId] = @p__linq__0) AND ([Project1].[ContactStatusId] <= 3) AND (0 = [Project1].[C1])
    )  AS [Project2]
)  AS [Project2]
WHERE [Project2].[row_number] > 99
ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4

Кажется, что чистый Where с EXISTS работает намного хуже, чем вычисление Count, а затем выполнение Where с Count == 0.

Дайте мне знать, если вы заметите ошибку в моих выводах. Что можно извлечь из всего этого, независимо от обсуждения Any vs Count, так это то, что любой более сложный LINQ будет намного лучше, если его переписать как хранимую процедуру;).

person nikib3ro    schedule 14.06.2012
comment
Хотелось бы увидеть некоторые планы запросов Sql, которые генерируются каждым запросом linq для каждого сценария. - person Pure.Krome; 15.06.2012
comment
на основе SQL все, что я могу сказать: оба запроса выглядят ужасно. Я знал, что есть причина, по которой я обычно пишу свой собственный TSQL ... - person Marc Gravell; 15.06.2012
comment
! Любому придется просмотреть все строки так же, как это сделал бы Граф. То, что ваш пример дает такой ужасный результат, в худшем случае немного странно! Any должен быть только немного медленнее, чем Count. В вашем случае я бы поискал способы упростить выбор, возможно, разделив его по этапам или переупорядочив условия, если это возможно. Но ваша точка зрения о том, что правило «Любое лучше, чем счет», не выполняется! - person Bent; 17.05.2016

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

Среда тестирования: EF 6.1.3, SQL Server, 300 КБ записей.

Настольная модель:

class TestTable
{
    [Key]
    public int Id { get; set; }

    public string Name { get; set; }

    public string Surname { get; set; }
}

Тестовый код:

class Program
{
    static void Main()
    {
        using (var context = new TestContext())
        {
            context.Database.Log = Console.WriteLine;

            context.TestTables.Where(x => x.Surname.Contains("Surname")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Any(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname")).Count(x => x.Id > 1000);
            context.TestTables.Where(x => x.Surname.Contains("Surname") && x.Name.Contains("Name")).Count(x => x.Id > 1000);

            Console.ReadLine();
        }
    }
}

Результаты:

Любой () ~ 3 мс

Count () ~ 230 мс для первого запроса, ~ 400 мс для второго

Примечания:

В моем случае EF не генерировал SQL, как @Ben, упомянутый в его сообщении.

person kamil-mrzyglod    schedule 28.05.2015
comment
Для правильного сравнения вы должны сделать Count() > 0. : D - person Andrew; 01.09.2017
comment
Эндрю, Count () ›0 не будет работать иначе, чем Count () в этом конкретном тесте. - person CodeMonkeyForHire; 20.07.2018

Точные детали немного отличаются в .NET Framework от .NET Core, но это также в некоторой степени зависит от того, что вы делаете: если вы используете тип ICollection или ICollection<T> (например, с List<T>), есть дешевое свойство .Count. для доступа, тогда как для других типов может потребоваться перечисление.

TL;DR:

Используйте .Count > 0, если свойство существует, в противном случае .Any().

Использование .Count() > 0 никогда не является лучшим вариантом, а в некоторых случаях может быть значительно медленнее.

Это относится как к .NET Framework, так и к .NET Core.


Теперь мы можем углубиться в детали ..

Списки и коллекции

Начнем с очень распространенного случая: использования List<T> (который тоже ICollection<T>).

Свойство .Count реализовано как:

    private int _size;

    public int Count {
        get {
            Contract.Ensures(Contract.Result<int>() >= 0);
            return _size; 
        }
    }

Это означает, что _size поддерживается _13 _, _ 14_ и т. Д., И поскольку он просто обращается к полю, это чрезвычайно дешевая операция - нам не нужно перебирать значения.

ICollection и ICollection<T> имеют .Count и большинство типов, реализующих их, вероятно, будут делать это аналогичным образом.

Другие IEnumerables

Любые другие IEnumerable типы, которые также не ICollection требуют начала перечисления, чтобы определить, пусты они или нет. Ключевым фактором, влияющим на производительность, является то, если мы в конечном итоге перечисляем один элемент (идеально) или всю коллекцию (относительно дорого).

Если коллекция на самом деле вызывает ввод-вывод, например, при чтении из базы данных или диска, это может сильно снизить производительность.


.NET Framework .Any()

В .NET Framework (4.8) реализация Any():

public static bool Any<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        if (e.MoveNext()) return true;
    }
    return false;
}

Это означает, что несмотря ни на что, он получит новый объект перечислителя и попытается выполнить итерацию один раз. Это дороже, чем вызов свойства List<T>.Count, но, по крайней мере, он не повторяет весь список.

.NET Framework .Count()

В .NET Framework (4.8) реализация Count() (в основном):

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

Если доступно, используется ICollection.Count, но в противном случае перечисляется коллекция.


.NET Core .Any()

Реализация LINQ Any() в .NET Core намного умнее. Вы можете увидеть, что завершено источник здесь, но важные части этого обсуждения:

    public static bool Any<TSource>(this IEnumerable<TSource> source)
    {
        //..snip..
        
        if (source is ICollection<TSource> collectionoft)
        {
            return collectionoft.Count != 0;
        }
        
        //..snip..

        using (IEnumerator<TSource> e = source.GetEnumerator())
        {
            return e.MoveNext();
        }
    }

Поскольку List<T> - это ICollection<T>, это вызовет свойство Count (и хотя он вызывает другой метод, дополнительных выделений нет).

.NET Core .Count()

Реализация .NET Core (source) в основном совпадает с .NET Framework (см. выше), поэтому он будет использовать ICollection.Count, если он доступен, а в противном случае перечисляет коллекцию.


Резюме

.NET Framework

  • С ICollection:

    • .Count > 0 is best
    • .Count() > 0 в порядке, но в конечном итоге просто звонит ICollection.Count
    • .Any() будет медленнее, так как перечисляет один элемент
  • Без ICollection (без свойства .Count)

    • .Any() is best, as it only enumerates a single item
    • .Count() > 0 плохо, так как вызывает полное перечисление

.NET Core

  • .Count > 0 лучше всего, если есть (ICollection)
  • .Any() в порядке, он либо выполнит ICollection.Count > 0, либо перечислит отдельный элемент
  • .Count() > 0 плохо, так как вызывает полное перечисление
person gregmac    schedule 24.08.2020

РЕДАКТИРОВАТЬ: это было исправлено в EF версии 6.1.1. и этот ответ больше не актуален

Для SQL Server и EF4-6 Count () работает примерно в два раза быстрее, чем Any ().

Когда вы запускаете Table.Any (), он сгенерирует что-то вроде (предупреждение: не повредите мозг, пытаясь понять это)

SELECT 
CASE WHEN ( EXISTS (SELECT 
    1 AS [C1]
    FROM [Table] AS [Extent1]
)) THEN cast(1 as bit) WHEN ( NOT EXISTS (SELECT 
    1 AS [C1]
    FROM [Table] AS [Extent2]
)) THEN cast(0 as bit) END AS [C1]
FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]

для этого требуется 2 сканирования строк с вашим состоянием.

Я не люблю писать Count() > 0, потому что это скрывает мои намерения. Я предпочитаю использовать для этого собственный предикат:

public static class QueryExtensions
{
    public static bool Exists<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
    {
        return source.Count(predicate) > 0;
    }
}
person Ben    schedule 03.01.2014
comment
Я тоже это заметил. Any () SQL вообще не имеет смысла. Я не уверен, почему они этого не делают: CASE WHEN (EXISTS (sql)) THEN 1 ELSE 0 END. Я не могу придумать причину, по которой им нужно сделать НЕ СУЩЕСТВУЕТ, чтобы вернуть 0. - person scott.korin; 23.03.2015
comment
Это неправда. Вы случайно обнаружили плохой план запроса. Это случилось. Any почти всегда быстрее. - person usr; 12.07.2015
comment
Я проверил sql, созданный в 6.1.3, они исправили его: SELECT CASE WHEN (EXISTS (SELECT 1 AS [C1] FROM [dbo]. [TestTables] AS [Extent1] WHERE [Extent1]. [Id] ›1000)) THEN преобразование (1 как бит) ELSE преобразование (0 как бит) END AS [C1] FROM (SELECT 1 AS X) AS [SingleRowTable1] - person Ben; 14.07.2015

Это зависит от того, насколько велик набор данных и каковы ваши требования к производительности?

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

person Timothy Gonzalez    schedule 22.12.2014

Вы можете провести простой тест, чтобы понять это:

var query = //make any query here
var timeCount = new Stopwatch();
timeCount.Start();
if (query.Count > 0)
{
}
timeCount.Stop();
var testCount = timeCount.Elapsed;

var timeAny = new Stopwatch();
timeAny.Start();
if (query.Any())
{
}
timeAny.Stop();
var testAny = timeAny.Elapsed;

Проверьте значения testCount и testAny.

person Bronks    schedule 20.01.2017
comment
Вот тест с вашим кодом для свойства Count против Any () Свойство Count выигрывает против Any () с + 2x - ссылка - person Stanislav Prusac; 16.04.2018
comment
Для лучшего результата вы можете повторить эти сравнения 1000 раз (или больше). Это помогает усреднить результаты и избежать случайных всплесков. - person Roman; 08.05.2018
comment
Когда вы тестируете, как вышеупомянутый метод, вам необходимо учитывать множество других факторов, таких как нагрузка на вашу базу данных / сеть, планирование кэширования на стороне базы данных и т. Д. Поэтому, чтобы провести точный тест, вы также должны спроектировать изолированную и точную среду. - person Vahid Farahmandian; 12.12.2018
comment
для лучшего сравнения нужно Count заменить на метод Count () vs. Any (), а не свойство. Вам нужно время итераций. - person daremachine; 26.05.2020

Что касается метода Count (), если IEnumarable является ICollection, то мы не можем выполнять итерацию по всем элементам, потому что можем получить < strong> Count поля ICollection, если IEnumerable не является ICollection, мы должны выполнить итерацию по всем элементам, используя а с помощью MoveNext взгляните на код .NET Framework:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) 
        throw Error.ArgumentNull("source");

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

    ICollection collection = source as ICollection;
    if (collection != null) 
        return collection.Count;

    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        checked
        {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}

Ссылка: Перечислимый справочный источник

person Thiago Coelho    schedule 28.03.2018

Если вы используете Entity Framework и имеете огромную таблицу с большим количеством записей, Any () будет намного быстрее. Я помню, как однажды я хотел проверить, пуста ли таблица и есть ли в ней миллионы строк. Для завершения Count ()> 0 потребовалось 20-30 секунд. Это было мгновенно с помощью Any ().

Any () может повысить производительность, поскольку ему, возможно, не придется повторять сборку, чтобы получить количество вещей. Он просто должен поразить одного из них. Или, скажем, для LINQ-to-Entities сгенерированный SQL будет IF EXISTS (...), а не SELECT COUNT ... или даже SELECT * ....

person Janmejay Kumar    schedule 11.03.2019

Я создал образец приложения с использованием IList с 100 элементами на 1 миллион элементов, чтобы увидеть Count vs Any, который лучше всего.

Код

class Program
{
    static void Main()
    {

        //Creating List of customers
        IList<Customer> customers = new List<Customer>();
        for (int i = 0; i <= 100; i++)
        {
            Customer customer = new Customer
            {
                CustomerId = i,
                CustomerName = string.Format("Customer{0}", i)
            };
            customers.Add(customer);
        }

        //Measuring time with count
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        if (customers.Count > 0)
        {
            Console.WriteLine("Customer list is not empty with count");
        }
        stopWatch.Stop();
        Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);

        //Measuring time with any
        stopWatch.Restart();
        if (customers.Any())
        {
            Console.WriteLine("Customer list is not empty with any");
        }
        stopWatch.Stop();
        Console.WriteLine("Time consumed with count: {0}", stopWatch.Elapsed);
        Console.ReadLine();

    }
}

public class Customer
{
    public int CustomerId { get; set; }
    public string CustomerName { get; set; }
}

Результат:  введите описание изображения здесь

Лучше любое, чем считать.

person RRaveen    schedule 15.06.2021
comment
Вы сравниваете .Count с .Any(), и с этими крошечными суммами все, что вы измеряете, - это время, необходимое для записи в консоль, которое сильно различается при каждом запуске. Без вызовов Console.WriteLine Count работает быстрее, что действительно не требует дополнительных доказательств. - person Gert Arnold; 15.06.2021
comment
@RRaveen - ознакомьтесь с github.com/dotnet/BenchmarkDotNet, чтобы узнать, как провести хороший сравнительный анализ кода C #. . Это тебе поможет, кучи! - person Pure.Krome; 15.06.2021