带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