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

6

假设我有以下方法。在某些情况下,这个方法可能会抛出异常并显示错误消息。但是,在其他情况下,它会返回一个值。

    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 

我该怎么办?


2
我认为错误信息非常明确。由于函数的执行被延迟到迭代器被调用时,因此无法混合使用yieldreturn。我建议去掉yield,自己构建枚举。但我希望Jon Skeet或Eric Lippert能够详细解释为什么编译器无法处理这种情况。 - Mike Christensen
3个回答

10

如果你只想返回一个元素的集合,可以这样做:

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

谢谢,这就是我需要的简单解决方案。 - parliament

4
正如错误提示所示,您不能将yield return语句和return语句混合在一个方法中。您有两种一般的方法:
  1. 这个方法应该被急切地评估;您应该使用所有的return语句,找到一种方法将所有的yield语句转换为return
  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关键字,以便您可以在迭代器块中yield一个集合,但目前尚未添加此类关键字到语言中。

1
谢谢您的回复,我学到了一些有用的东西,将来会派上用场。但在这种情况下,我更喜欢保持我在所有地方使用的相同模式(yield return),只是在特殊情况下返回单个元素。Paul Phillips的答案简单而有效。肯定点赞。 - parliament

3

那个返回语句应该是一个yield吗?

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

如果您确实需要返回一个集合,您也可以使用yield return返回一个集合(就像现在这样),只是不必要,因为您只有一个。

此外,在您希望明确停止枚举的情况下,您可以使用yield break;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接