5

假设我有以下方法。在一些来

    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 

我应该怎么办?

4

3 回答 3

10

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

if(!user.Activated)
{
  yield return new ValidationResult("NotActived", Resources.UserNotActivated);
  yield break;
}
于 2012-12-19T22:05:16.973 回答
4

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

您有两种通用方法:

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

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

现在,如何将 ayield变成 a return

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

return new[]{ someItemToReturn };

或者

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

现在,如何将 areturn变成 a yield

foreach(var item in collectionYouWereReturning)
    yield return item;

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

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

于 2012-12-19T22:07:38.910 回答
3

该 return 语句实际上不应该是一个收益吗?

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

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

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

于 2012-12-19T22:01:53.663 回答