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.
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.
This is because the debugger is only attached to your running process not visual studio itself. If you opened a 2nd copy of visual studio, attached a debugger to the first copy of visual studio, then put a breakpoint inside the code in the 2nd copy that breakpoint would get hit when you evaluated the list in the first copy of visual studio (and the first copy of visual studio would hang till you hit continue on the 2nd copy).
EDIT: Thanks to Brian's link, the way this is done is via FuncEval.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With