【问题标题】:Returning a single element from an iterator block - Iterator cannot contain return statement从迭代器块返回单个元素 - 迭代器不能包含返回语句
【发布时间】:2012-12-07 08:47:27
【问题描述】:

假设我有以下方法。有的来了

    public IEnumerable<ValidationResult> Validate(UserLoginCommand command)
    {
        User user = userRepository.Get(u => u.Email == command.UserEmail);
        if(user != null)
        {
            if(!user.Activated)
            {
                return new IEnumerable<ValidationResult>() {new ValidationResult("NotActived", Resources.UserNotActivated)};
            }

            if(user.IsPasswordIncorrent)
            {

                yield return new ValidationResult("IncorrectPassword", Resources.IncorrentPassword);

            }

        }
    }

实际情况其实要复杂一些,但为了说明,我省略了很多。

重点是在某些情况下,我希望迭代器继续收集多个错误...但在其他情况下,会出现致命错误,我只想返回一个错误但它不会让我:

Iterator cannot contain return statement 

我该怎么办?

【问题讨论】:

  • 我认为错误信息非常明确。您不能混合使用yieldreturn,因为函数执行会延迟到迭代器被调用。我建议摆脱 yield 并构建自己的枚举。我希望 Jon Skeet 或 Eric Lippert 能在这里准确地解释为什么编译器无法处理这种情况。

标签: c# .net c#-4.0 iterator yield


【解决方案1】:

那个return语句不应该是一个yield吗?

yield return ValidationResult("NotActived", Resources.UserNotActivated);

如果你真的需要返回一个集合,你也可以yield return一个集合(就像你有它一样),因为你只有一个,所以没有必要。

另外,如果你想停止显式枚举,你可以使用yield break;

【讨论】:

    【解决方案2】:

    如果你只想返回一个大小为 1 的集合,你可以这样做:

    if(!user.Activated)
    {
      yield return new ValidationResult("NotActived", Resources.UserNotActivated);
      yield break;
    }
    

    【讨论】:

    • 谢谢,这是我需要的简单解决方案。
    【解决方案3】:

    如错误消息所示,您不能将yield return 语句和return 语句混合到一个方法中。

    您有两种通用方法:

    1. 应积极评估该方法;您应该使用所有return 语句,找到一种方法将所有yield 语句转换为返回。
    2. 该方法应该使用延迟执行,想办法将所有return语句变成yield语句。

    在你的情况下,它可能是 #2,但在其他情况下,任何一个都可能是合适的。

    现在,如何将yield 变成return

    将单个元素包装成某种集合并返回:

    return new[]{ someItemToReturn };
    

    return Enumerable.Repeat<T>(someItemToReturn, 1);
    

    现在,如何将return 变成yield

    foreach(var item in collectionYouWereReturning)
        yield return item;
    

    您可以使用yield break; 指示序列已结束,即使该方法尚未达到其自然结束。请注意,yield break; 应该很少使用。经常使用它会产生代码异味(但这似乎是合适的情况)。

    现在,理想情况下,我们应该有一个 yield foreach 某种关键字,这样您就可以在迭代器块内产生一个集合,但目前还没有这样的关键字被添加到该语言中。

    【讨论】:

    • 感谢您的回复,我学到了一些对未来有用的东西,但在这种情况下,我更喜欢保持我在任何地方使用的相同模式(收益返回),但只返回一个特殊情况下的要素。保罗菲利普斯的回答很简单而且有效。一定要点赞。
    猜你喜欢
    • 2021-06-11
    • 1970-01-01
    • 2016-04-24
    • 2010-09-23
    • 1970-01-01
    • 2014-06-16
    • 2021-12-26
    • 2019-06-23
    • 2018-06-15
    相关资源
    最近更新 更多