In IEnumerable extensions - why is only Count () optimized for ICollection?

After decompiling the Linq IEnumerable extension methods, I was glad to see that
The Count() method, before trying to iterate through all the enumerable, tries to reset it to an ICollection or ICollection<T> for example:

  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; } 

Why doesn't this happen in Any() ? wouldn't it be useful to use .Count > 0 instead of creating an array counter?

+6
source share
2 answers

Not all collections provide O (1) access for the Count property. For example, access to the count property ConcurrentQueue<T> is O (n). Thus, optimization will make it worse and therefore should not be called optimization.

Not only ConcurrentQueue<T> , almost all concurrent collections ( ConcurrentDictionary<TKey,TValue> , ConcurrentStack<T> , etc.) fall into this category

Perhaps that’s why they decided not to.

+5
source

Nope. The cost of the code will always be more than any possible gain from growth, which is substantially equal to zero. Do not forget that the whole LINQ point is a chain of such expressions, so you are most likely using Any either with a predicate or with its own set of filters, etc. Before.

In which case, when would you use Any as an alternative to Count ? Even the optimization of Count has a very subtle use of IMO - if you do Count() inside some logic that expects IEnumerable as a parameter, you are probably mistaken - at least you tend to list the enumerated several times, which is likely to break that or will kill your performance: D

Do not forget that as soon as you do something in this enumerated array, you have lost the "array", for example. categories.Where(i => i.Name.StartsWith("Hello")).Count() will not use the abbreviation.

And, of course, the cost of an enumerator on any empty enumerable is likely to be quite free. An enumerator is just a simple structure, and there will also be no costly initialization in the array.

0
source

Source: https://habr.com/ru/post/976364/


All Articles