Search code examples
c#linqvisual-studioenumeratorienumerator

How does Visual Studio evaluate the IEnumerable without breaking into its IEnumerator<T>'s MoveNext?


Let's say you wrote a custom enumerator for the code below:

public class School : IEnumerable<Student>

And then in the client code, you did this:

static void Main(string[] args)
{
    var school = CreateSchoolWithStudents();

    var query = from student in school
                where student.Name.StartsWith("S")
                select student;

    Debugger.Break();
}

private static School CreateSchoolWithStudents()
{
    return new School
    {
        new Student { Name = "Sathyaish" },
        new Student { Name = "John" },
        new Student { Name = "Carol" },
        new Student { Name = "Peter" }
    };
}

Then, set a break-point on the MoveNext method implementation of your StudentEnumerator class.

Then when you run the code and the debugger breaks after constructing the query / IEnumerable in this case, and you expand the Results View like in the picture shown below, how does Visual Studio evaluate the sequence without breaking into its enumerator's MoveNext?

I have always been curious about this.

enter image description here


Solution

  • Visual Studio uses a feature called FuncEval, which basically lets the IDE run your code. This enables a lot of nice features, but obviously there are numerous caveats of doing so. Examples are side effects on properties, deadlocks, skipping steps in a loop, and weird debugging experiences.