Problem with debug watch in Visual Studio with yield return enumerator methods
I have a method which returns an IEnumerable<>
which it builds up using the yield return
syntax:
namespace Validation
{
public class UserValidator
{
public IEnumerable<ValidationError> Validate(User user)
{
if (String.IsNullOrEmpty(user.Name))
{
yield return new ValidationError("Name", ValidationErrorType.Required);
}
[...]
yield break;
}
}
}
If I put a breakpoint in the method, I can step over each line, but if I try to use the Watch or Immediate开发者_如何学运维 windows to view the value of a variable I get this error:
Cannot access a non-static member of outer type 'Validation.UserValidator.Validate' via nested type 'Validation.UserValidator'
Does anyone know why this is and how I can get around it?
OK, just tried it out and I see what you mean. That's painful! I suspect it has to do with the behind-the-scenes work the compiler does (creating nested classes and such) to implement the resumable state machine-type logic for yield
. One way of getting around it (the way I originally tried your code) is to make the Validate
method static, though obviously that's not great for the design.
I think the reason the error message is so obtuse is some combination of:
- The generated classes don't exist in your source, so VS has no names by which to refer to them.
- IIRC, the names generated by the compiler contain characters illegal in C# identifiers, but valid in the underlying Framework type system.
I don't have Reflector handy right now, so can't confirm, but if you're feeling like a spot of light masochism, reflect on your assembly and take a look at the code the compiler writes to let us mere mortals use nice syntactic sugar like yield return
:) There's lots of information available on the web on how exactly it all works.
Edit: after a little more searching, a couple of the better ones:
http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx
The method isn't run until you enumerate into it.
var p = UserValidator.Validate(user).ToList();
You can now debug your code.
I've had similar problems, and what I have done is to modify the implementation to build up a list of elements, and then return the list.
That has allowed me to find the bug, correct it. After the bug has been corrected, I change the implementation back to a yield return.
Painful.
精彩评论