title: Count an IOrderedEnumerable without consuming it
body: <p>What I want to do, short version:</p>
  
  <pre><code>var source = new[]{2,4,6,1,9}.OrderBy(x=&gt;x);
  int count = source.Count; // &lt;-- get the number of elements without performing the sort
  </code></pre>
  
  <hr>
  
  <p><em>Long version:</em></p>
  
  <p>To determine the number of elements in an <em>IEnumerable</em>, it is neccessary to iterate over all elements. This could potentially be a very expensive operation.</p>
  
  <p>If the <em>IEnumerable</em> can be cast to <em>ICollection</em>, then the count can be determined quickly without iterating. The LINQ Count() method does this automatically.</p>
  
  <p>The function <em>myEnumerable.OrderBy()</em> returns an <em>IOrderedEnumerable</em>. An <em>IOrderedEnumerable</em> can obviously not be cast to <em>ICollection</em>, so calling <em>Count()</em> will consume the whole thing.</p>
  
  <p>But sorting does not change the number of elements, and an <em>IOrderedEnumerable</em> has to keep a reference to its source. So if that source is an <em>ICollection</em>, it should be possible to determine the count from the <em>IOrderedEnumerable</em> without consuming it.</p>
  
  <p>My goal is to have a library method, that takes an <em>IEnumerable</em> with n elements, and then for example retrieves the element at position n/2;</p>
  
  <p>I want to avoid iterating over the <em>IEnumerable</em> twice just to get its count, but I also want to avoid creating an unnecessary copy if at all possible.</p>
  
  <hr>
  
  <p>Here is a skeleton of the function I want to create</p>
  
  <pre><code>public void DoSomething(IEnumerable&lt;T&gt; 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
  
  }
  </code></pre>