How to tell if an IEnumerable<T> is subject to deferred execution?

Deferred execution of LINQ has trapped a lot of people, you're not alone.

The approach I've taken to avoiding this problem is as follows:

Parameters to methods - use IEnumerable<T> unless there's a need for a more specific interface.

Local variables - usually at the point where I create the LINQ, so I'll know whether lazy evaluation is possible.

Class members - never use IEnumerable<T>, always use List<T>. And always make them private.

Properties - use IEnumerable<T>, and convert for storage in the setter.

public IEnumerable<Person> People 
{
    get { return people; }
    set { people = value.ToList(); }
}
private List<People> people;

While there are theoretical cases where this approach wouldn't work, I've not run into one yet, and I've been enthusiasticly using the LINQ extension methods since late Beta.

BTW: I'm curious why you use ToArray(); instead of ToList(); - to me, lists have a much nicer API, and there's (almost) no performance cost.

Update: A couple of commenters have rightly pointed out that arrays have a theoretical performance advantage, so I've amended my statement above to "... there's (almost) no performance cost."

Update 2: I wrote some code to do some micro-benchmarking of the difference in performance between Arrays and Lists. On my laptop, and in my specific benchmark, the difference is around 5ns (that's nanoseconds) per access. I guess there are cases where saving 5ns per loop would be worthwhile ... but I've never come across one. I had to hike my test up to 100 million iterations before the runtime became long enough to accurately measure.


In general, I'd say you should try to avoid worrying about whether it's deferred.

There are advantages to the streaming execution nature of IEnumerable<T>. It is true - there are times that it's disadvantageous, but I'd recommend just always handling those (rare) times specifically - either go ToList() or ToArray() to convert it to a list or array as appropriate.

The rest of the time, it's better to just let it be deferred. Needing to frequently check this seems like a bigger design problem...


My five cents. Quite often you have to deal with an enumerable that you have no idea what's inside of it.

Your options are:

  • turn it to a list before using it but chances are it's endless you are in trouble
  • use it as is and you are likely to face all kinds of deferred execution funny things and you are in trouble again

Here is an example:

[TestClass]
public class BadExample
{
    public class Item
    {
        public String Value { get; set; }
    }
    public IEnumerable<Item> SomebodysElseMethodWeHaveNoControlOver()
    {
        var values = "at the end everything must be in upper".Split(' ');
        return values.Select(x => new Item { Value = x });
    }
    [TestMethod]
    public void Test()
    {
        var items = this.SomebodysElseMethodWeHaveNoControlOver();
        foreach (var item in items)
        {
            item.Value = item.Value.ToUpper();
        }
        var mustBeInUpper = String.Join(" ", items.Select(x => x.Value).ToArray());
        Trace.WriteLine(mustBeInUpper); // output is in lower: at the end everything must be in upper
        Assert.AreEqual("AT THE END EVERYTHING MUST BE IN UPPER", mustBeInUpper); // <== fails here
    }
}

So there is no way to get away with it but the one: iterate it exactly one time on as-you-go basis.

It was clearly a bad design choice to use the same IEnumerable interface for immediate and deferred execution scenarios. There must be a clear distinction between these two, so that it's clear from the name or by checking a property whether or not the enumerable is deferred.

A hint: In your code consider using IReadOnlyCollection<T> instead of the plain IEnumerable<T>, because in addition to that you get the Count property. This way you know for sure it's not endless and you can turn it to a list no problem.