Wilbert
Wilbert

Reputation: 7399

LINQ unexpected behavior when returning IEnumerable and calling ToArray

I noticed some weird behavior in LINQ-code, and reduced the problem to the following minimal example with two methods:

IA Find(string n)
{
    IA result;
    if (!_dictionary.TryGetValue(n, out result))
    {
        throw Exception();
    }
    return result;
}

IEnumerable<IA> Find(IEnumerable<string> names)
{
    return names.Select(Find).ToArray();
}

This works as expected.

Now, I remove the .ToArray() so the method looks as follows:

IEnumerable<IA> Find(IEnumerable<string> names)
{
    return names.Select(Find);
}

This change will cause the exception not to be thrown, even if some of the names are not found in _dictionary, but are present in the names parameter.

What causes this (to me) unexpected behavior of LINQ?

Upvotes: 1

Views: 230

Answers (1)

Jodrell
Jodrell

Reputation: 35696

Its because of deferred execution. The Linq is not evaluated until you execute it.

The call to ToArray() causes a full enumeration of the IEnumerable and thus, the exception to occur.

The second method does not enumerate the IEnumerable and execution is deferred until the caller needs it.


If you were to enumerate the result of Find e.g.

var result = Find(new[] { "name" }).ToList();

or

foreach (var found in Find(new[] { "name" }))
{
    ...
}

then the exception would occur.

Upvotes: 14

Related Questions