2013-08-12 1 views
3

Я извлекаю список элементов, используя Entity Framework, и если есть какие-то найденные элементы, я что-то делаю с ними.IEnumerable Count() vs List <T> .Count с платформой Entity

var items = db.MyTable.Where(t => t.Expiration < DateTime.Now).ToList(); 
if(items.Count != 0) 
{ 
    // Do something... 
} 

if заявление также может быть записана в виде

if(items.Count() != 0) 
{ 
    // Do something... 
} 

В первом случае .Count является List<T>.Count собственностью. Во втором случае .Count() - это метод расширения IEnumerable<T>.Count().

Хотя оба подхода достигают такого же результата, однако, являются более предпочтительными, чем другие? (Возможно некоторое различие в производительности?)

+2

'Enumerable.Count' имеет то преимущество, что вы можете изменить тип последовательности позже, не нарушая код. Но обратите внимание, что 'Any' лучше, так как' Count() 'перечисляет всю последовательность, если это не коллекция, тогда как' Any' останавливается в первом элементе. Это также более читаемо. –

+0

@TimSchmelter, но у него есть недостаток, если вы не измените тип последовательности :) –

+0

@lazyberezovsky: Единственным недостатком является то, что он часто используется, даже если 'Any' будет лучше (см. Мое редактирование). –

ответ

8

Enumerable.Count<T> (метод расширения для IEnumerable<T>) просто вызывает Count если базовый тип является ICollection<T>, так что для List<T> нет никакой разницы.

Queryable.Count<T> (метод расширения для IQueryable<T>) будет использовать основной провайдер запроса, который во многих случаях будет толкать обратный отсчет фактического SQL, который будет работать быстрее, чем подсчет объектов в памяти.

Если применяется фильтр (например, Count(i => i.Name = "John")), или если базовый тип не является ICollection<T>, коллекция подсчитывается для вычисления счета.

является еще одним предпочтительным, чем другой?

Я вообще предпочитаю использовать Count() с 1) это более портативными (основной тип может быть все, что реализует IEnumerable<T> или IQueryable<T>) и 2), что легче добавить фильтр позже, если это необходимо.

Как Тим заявляет в своем комментарии, я также предпочитаю использовать Any() до Count() > 0, так как он не должен фактически подсчитывать элементы - он просто проверяет наличие одного элемента. И наоборот, я использую !Any() вместо Count() == 0.

+3

+1 для недоиспользуемых '! Items.Any()' –

2

Это зависит от базовой коллекции и от которой Линк будет тянуть. Например, если это SQL, то использование .ToList() приведет к тому, что запрос вернет весь список, а затем подсчитает его. Тем не менее, метод расширения .Count() переведет его в оператор SQL COUNT на стороне базы данных. В этом случае будет очевидная разница в производительности.

Для стандартного списка или коллекции это указано в ответе Д. Стэнли.

1

Я бы сказал, что это зависит от того, что происходит внутри блока if. Если вы просто выполняете проверку, чтобы определить, выполнять ли последовательность операций в базовом перечислении, тогда, вероятно, это не нужно ни в коем случае. Просто перебирайте нумерацию (исключая также ToList). Если вы не используете коллекцию внутри блока if, вам следует избегать использования ToList и определенно использовать Any по любому методу Count/Count().

После того, как вы выполнили ToList тогда вы больше не используете Entity Framework, и я ожидаю, что Count() лишь незначительно медленнее, чем Count, поскольку, если основной коллекции ICollection<T> она сдвинуто этой реализации. Единственные накладные расходы будут определять, реализует ли он этот интерфейс.

http://msdn.microsoft.com/en-us/library/bb338038.aspx

Примечание: Если тип источника реализует ICollection<T>, используется, что реализация получить количество элементов. В противном случае этот метод определяет счетчик.

+0

Не могли бы вы подробнее остановиться на 'Если вы просто делаете проверку, чтобы определить, следует ли выполнять последовательность операций над базовым перечислением, тогда это, вероятно, не понадобится ни в каком случае .'? – erdinger

+1

Ну, если ваш чек просто 'if (items.Any()) {foreach (элемент var в элементах) {....}}', тогда вам не нужно сначала проверять. Если в коллекции нет элементов, цикл 'foreach' работает так же хорошо. – tvanfosson