Question

What is the difference between returning Select() and yield return?

Examples:

public IEnumerable<Class> ReturnClass()
{
    var list = ...;

    return list.Select(item =>
    {
        // if, else, etc

        return item;
    });
}

or

public IEnumerable<Class> ReturnClass()
{
    var list = ...;

    foreach (var item in list)
    {
        // if, else, etc

        yield return item;
    }
}

Are there differences in the generated code? Performance? Etc

I only found one question on stackoverflow about this subject, but it raised more questions than it answered questions

 3  124  3
1 Jan 1970

Solution

 3

The main differences is that yield return creates state machine and thus executes lazily. Lazy execution can be problematic in case of validation, let me show some toy example:

// State Machine, Lazy execution
public IEnumerable<int> ReturnClassLazy(int count)
{
    // Validation (will be called lazily)
    if (count < 0)
        throw new ArgumentOutOfRangeException(nameof(count));

    var list = Enumerable.Range(1, count);

    foreach (var item in list) 
        yield return item * item;
}

// Eager execution
public IEnumerable<int> ReturnClassEager(int count)
{
    // Validation (will be called eagerly)
    if (count < 0)
        throw new ArgumentOutOfRangeException(nameof(count));

    var list = Enumerable.Range(1, count);

    return list.Select(item => item * item);
}

In case of eager version (when we return Select(...)), the method will be executed immediately (note, that validation will be called):

// ArgumentOutOfRangeException is thrown (invalid count argument, -1)
var result = ReturnClassEager(-1);

while in case of lazy call (yield return version)

// Nothing happens (even if count argument -1 is invalid)
var result = ReturnClassLazy(-1);

... /* imagine 10000 lines of code here */

// Only here (when we materialize) 
// the exception is thrown due to invalid count argument -1
int sum = result.Sum();

Usually, we want validation exception be thrown as early as possible, that's why eager version is easier to maintain.

2024-07-12
Dmitry Bychenko