从迭代器块返回单个元素 - 迭代器不能包含return语句

时间:2012-12-19 21:53:30

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

假设我有以下方法。有些人来了

    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 

我该怎么办?

3 个答案:

答案 0 :(得分:10)

如果您只想返回大小为1的集合,则可以执行以下操作:

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

答案 1 :(得分:3)

该返回语句实际上不应该是收益吗?

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

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

此外,如果您要明确停止枚举,可以使用yield break;

答案 2 :(得分:3)

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

您有两种常规方法:

  1. 应该热切评估该方法;您应该使用所有return语句,找到将所有yield语句转换为返回的方法。
  2. 该方法应使用延迟执行,找到将所有return语句转换为yield语句的方法。
  3. 在你的情况下,它可能是#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关键字,以便您可以在迭代器块中生成一个集合,但截至目前还没有添加这样的关键字。