问题 使用yield return枚举器方法在Visual Studio中进行调试监视的问题


我有一个返回的方法 IEnumerable<> 它是用它构建的 yield return 句法:

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;
        }
    }
}

如果我在方法中放置一个断点,我可以跨越每一行,但如果我尝试使用Watch或Immediate窗口来查看变量的值,我会收到此错误:

无法访问非静态成员   外部类型'Validation.UserValidator.Validate'via   嵌套类型'Validation.UserValidator'

有谁知道这是为什么以及如何绕过它?


10243
2018-05-28 08:14


起源



答案:


好的,试了一下,我明白了你的意思。那太痛苦了!我怀疑它与编译器所做的幕后工作(创建嵌套类等)有关,以实现可恢复的状态机类型逻辑 yield。绕过它的一种方式(我最初尝试你的代码的方式)就是制作它 Validate 方法静态,虽然显然这对设计来说并不好。

我认为错误消息如此迟钝的原因是:

  1. 生成的类在您的源中不存在,因此VS没有用于引用它们的名称。
  2. IIRC,编译器生成的名称包含C#标识符中的非法字符,但在底层Framework类型系统中有效。

我现在没有Reflector方便,所以无法确认,但是如果你感觉像一个光受虐狂的地方,反思你的程序集并看一看编译器编写的代码让我们凡人使用不错句法糖就像 yield return :)网上有很多关于它是如何工作的信息。

编辑: 经过一番搜索,有几个更好的:
http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx


7
2018-05-28 08:59



感谢回复shambulator。我想那时“我怎么能解决它”问题的答案是“你不能不改变你的设计”? - stusherwin
非常害怕,至少就我所知。 - shambulator


答案:


好的,试了一下,我明白了你的意思。那太痛苦了!我怀疑它与编译器所做的幕后工作(创建嵌套类等)有关,以实现可恢复的状态机类型逻辑 yield。绕过它的一种方式(我最初尝试你的代码的方式)就是制作它 Validate 方法静态,虽然显然这对设计来说并不好。

我认为错误消息如此迟钝的原因是:

  1. 生成的类在您的源中不存在,因此VS没有用于引用它们的名称。
  2. IIRC,编译器生成的名称包含C#标识符中的非法字符,但在底层Framework类型系统中有效。

我现在没有Reflector方便,所以无法确认,但是如果你感觉像一个光受虐狂的地方,反思你的程序集并看一看编译器编写的代码让我们凡人使用不错句法糖就像 yield return :)网上有很多关于它是如何工作的信息。

编辑: 经过一番搜索,有几个更好的:
http://blogs.msdn.com/b/ericlippert/archive/tags/iterators/
http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx


7
2018-05-28 08:59



感谢回复shambulator。我想那时“我怎么能解决它”问题的答案是“你不能不改变你的设计”? - stusherwin
非常害怕,至少就我所知。 - shambulator


在枚举之前,该方法不会运行。

var p = UserValidator.Validate(user).ToList();

您现在可以调试代码。


4
2017-11-14 15:52



我想你可能误解了这个问题:) - stusherwin


我遇到了类似的问题,我所做的是修改实现以构建元素列表,然后返回列表。

这让我找到了错误,纠正了它。错误更正后,我将实现更改回收益率返回。

痛苦。


3
2017-09-06 08:55