title: Best practice for parameter: IEnumerable vs. IList vs. IReadOnlyCollection
body: <p>I get when one would <strong>return</strong> an <code>IEnumerable</code> from a method—when there's value in deferred execution. And returning a <code>List</code> or <code>IList</code> should pretty much be only when the result is going to be modified, otherwise I'd return an <code>IReadOnlyCollection</code>, so the caller knows what he's getting isn't intended for modification (and this lets the method even reuse objects from other callers).</p>
  
  <p>However, on the <strong>parameter</strong> input side, I'm a little less clear. I <em>could</em> take an <code>IEnumerable</code>, but what if I need to enumerate more than once?</p>
  
  <p>The saying "<em>Be conservative in what you send, be liberal in what you accept</em>" suggests taking an <code>IEnumerable</code> is good, but I'm not really sure.</p>
  
  <p>For example, if there are no elements in the following <code>IEnumerable</code> parameter, a significant amount of work can be saved in this method by checking <code>.Any()</code> first, which requires <code>ToList()</code> before that to <strong>avoid enumerating twice</strong>.</p>
  
  <pre><code>public IEnumerable&lt;Data&gt; RemoveHandledForDate(IEnumerable&lt;Data&gt; data, DateTime dateTime) {
     var dataList = data.ToList();
  
     if (!dataList.Any()) {
        return dataList;
     }
  
     var handledDataIds = new HashSet&lt;int&gt;(
        GetHandledDataForDate(dateTime) // Expensive database operation
           .Select(d =&gt; d.DataId)
     );
  
     return dataList.Where(d =&gt; !handledDataIds.Contains(d.DataId));
  }
  </code></pre>
  
  <p>So I'm wondering what is the best signature, here? One possibility is <code>IList&lt;Data&gt; data</code>, but accepting a list suggests that you plan to modify it, which is not correct—this method doesn't touch the original list, so <code>IReadOnlyCollection&lt;Data&gt;</code> seems better.</p>
  
  <p>But <code>IReadOnlyCollection</code> forces callers to do <code>ToList().AsReadOnly()</code> every time which gets a bit ugly, even with a custom extension method <code>.AsReadOnlyCollection</code>. And that's not being liberal in what is accepted.</p>
  
  <p>What is best practice in this situation?</p>
  
  <p>This method is not returning an <code>IReadOnlyCollection</code> because there may be value in the final <code>Where</code> using deferred execution as the whole list is not <em>required</em> to be enumerated. However, the <code>Select</code> is required to be enumerated because the cost of doing <code>.Contains</code> would be horrible without the <code>HashSet</code>.</p>
  
  <p>I don't have a problem with calling <code>ToList</code>, it just occurred to me that if I need a <code>List</code> to avoid multiple enumeration, why do I not just ask for one in the parameter? So the question here is, if I don't want an <code>IEnumerable</code> in my method, should I really accept one in order to be liberal (and <code>ToList</code> it myself), or should I put the burden on the caller to <code>ToList().AsReadOnly()</code>?</p>
  
  <p><strong>Further Information for those unfamiliar with IEnumerables</strong></p>
  
  <p>The real problem here is not the cost of <code>Any()</code> vs. <code>ToList()</code>. I understand that enumerating the entire list costs more than doing <code>Any()</code>. However, assume the case that the caller will consume all items in the return <code>IEnumerable</code> from the above method, and assume that the source <code>IEnumerable&lt;Data&gt; data</code> parameter comes from the result of this method:</p>
  
  <pre><code>public IEnumerable&lt;Data&gt; GetVeryExpensiveDataForDate(DateTime dateTime) {
      // This query is very expensive no matter how many rows are returned.
      // It costs 5 seconds on each `.GetEnumerator` call to get 1 value or 1000
      return MyDataProvider.Where(d =&gt; d.DataDate == dateTime);
  }
  </code></pre>
  
  <p>Now if you do this:</p>
  
  <pre><code>var myData = GetVeryExpensiveDataForDate(todayDate);
  var unhandledData = RemoveHandledForDate(myData, todayDate);
  foreach (var data in unhandledData) {
     messageBus.Dispatch(data); // fully enumerate
  )
  </code></pre>
  
  <p>And if <code>RemovedHandledForDate</code> does <code>Any</code> <em>and</em> does <code>Where</code>, you'll incur the 5 second cost <em>twice</em>, instead of once. This is why <strong>you should always take extreme pains to avoid enumerating an <code>IEnumerable</code> more than once</strong>. Do not rely on your knowledge that in fact it's harmless, because some future hapless developer may call your method some day with a newly implemented <code>IEnumerable</code> you never thought of, which has different characteristics.</p>
  
  <p>The contract for an <code>IEnumerable</code> says that you can enumerate it. It does NOT promise anything about the performance characteristics of doing so more than once.</p>
  
  <p>In fact, some <code>IEnumerables</code> are <em>volatile</em> and won't return any data upon a subsequent enumeration! Switching to one would be a totally breaking change if combined with multiple enumeration (and a very hard to diagnose one if the multiple enumeration was added later).</p>
  
  <p>Don't do multiple enumeration of an IEnumerable.</p>
  
  <p><em>If you accept an IEnumerable parameter, you are in effect <strong>promising</strong> to enumerate it exactly 0 or 1 times.</em></p>