What I want to do is short version:
var source = new[]{2,4,6,1,9}.OrderBy(x=>x); int count = source.Count;
Long version:
To determine the number of elements in IEnumerable, you need to iterate over all the elements. This can be a very expensive operation.
If IEnumerable can be attributed to ICollection, then the score can be quickly determined without repetition. The LINQ Count () method does this automatically.
The myEnumerable.OrderBy () function returns the value of IOrderedEnumerable. Obviously, IOrderedEnumerable cannot be attributed to ICollection, so calling Count () will consume all of this.
But sorting does not change the number of elements, and IOrderedEnumerable should contain a link to its source. Therefore, if this source is an ICollection, it should be able to determine the counter from IOrderedEnumerable without consuming it.
My goal is to have a library method that takes an IEnumerable with n elements, and then, for example, extracts the element at position n / 2;
I want to avoid repeating IEnumerable twice to get its score, but I also want to avoid making an unnecessary copy, if at all possible.
Here is the skeleton of the function I want to create
public void DoSomething(IEnumerable<T> source) { int count; // What we do with the source depends on its length if (source is ICollection) { count = source.Count(); // Great, we can use ICollection.Count } else if (source is IOrderedEnumerable) { // TODO: Find out whether this is based on an ICollection, // TODO: then determine the count of that ICollection } else { // Iterating over the source may be expensive, // to avoid iterating twice, make a copy of the source source = source.ToList(); count = source.Count(); } // do some stuff }