带IEnumerable的嵌套收益率回报

我有以下功能来获取卡的验证错误。 我的问题涉及处理GetErrors。 两种方法都有相同的返回类型IEnumerable<ErrorInfo>

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    var errors = GetMoreErrors(card);
    foreach (var e in errors)
        yield return e;

    // further yield returns for more validation errors
}

是否有可能返回GetMoreErrors所有错误,而不必通过它们枚举?

考虑这可能是一个愚蠢的问题,但我想确保我不会出错。


这绝对不是一个愚蠢的问题,它是F#支持yield!的东西yield! 对于单个项目的整个收藏与yield 。 (就尾递归而言,这可能非常有用...)

不幸的是,它在C#中不受支持。

但是,如果您有多个方法返回一个IEnumerable<ErrorInfo> ,则可以使用Enumerable.Concat简化代码:

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    return GetMoreErrors(card).Concat(GetOtherErrors())
                              .Concat(GetValidationErrors())
                              .Concat(AnyMoreErrors())
                              .Concat(ICantBelieveHowManyErrorsYouHave());
}

尽管两个实现之间有一个非常重要的区别:即使它只会一次使用返回的迭代器,但它会立即调用所有方法。 你现有的代码会等到GetMoreErrors()所有内容循环播放之后,它才会询问下一个错误。

通常这并不重要,但值得了解什么时候会发生。


你可以像这样设置所有的错误来源(方法名称来自Jon Skeet的答案)。

private static IEnumerable<IEnumerable<ErrorInfo>> GetErrorSources(Card card)
{
    yield return GetMoreErrors(card);
    yield return GetOtherErrors();
    yield return GetValidationErrors();
    yield return AnyMoreErrors();
    yield return ICantBelieveHowManyErrorsYouHave();
}

然后你可以同时迭代它们。

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    foreach (var errorSource in GetErrorSources(card))
        foreach (var error in errorSource)
            yield return error;
}

或者,您可以使用SelectMany压扁错误来源。

private static IEnumerable<ErrorInfo> GetErrors(Card card)
{
    return GetErrorSources(card).SelectMany(e => e);
}

GetErrorSources方法的执行也会被延迟。


我想出了一个快速yield_片段:

以下是代码片段XML:

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Author>John Gietzen</Author>
      <Description>yield! expansion for C#</Description>
      <Shortcut>yield_</Shortcut>
      <Title>Yield All</Title>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal Editable="true">
          <Default>items</Default>
          <ID>items</ID>
        </Literal>
        <Literal Editable="true">
          <Default>i</Default>
          <ID>i</ID>
        </Literal>
      </Declarations>
      <Code Language="CSharp"><![CDATA[foreach (var $i$ in $items$) yield return $i$$end$;]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
链接地址: http://www.djcxy.com/p/53755.html

上一篇: Nested yield return with IEnumerable

下一篇: Convert DataTable to IEnumerable<T>