使用yield时,在try / catch中包含对iterator的调用

时间:2016-02-11 11:57:28

标签: c# try-catch yield-return

我需要在一个方法中做一些沉重的,有点脆弱的逻辑,我将它作为迭代器实现(使用yield):

public IEnumerable<Things> GetMoreThings() {
    while (goodStuffHappens()) {
        Things moreThingsIWant = TemptFateAgain();
        if (moreThingsIWant.Any())
            yield return moreThingsIWant;
    }
}

在调用方法中,我需要将调用包含在GetMoreThings / trycatchyield return结果:

try {
    foreach (Things thing in Helpful.GetMoreThings())
        yield return thing;
}

catch (Exception e) {
    //crash, burn
}

发起人将立即意识到这是不可能的 - there is no such thing as a yield inside a try/catch block(仅try / finally)。

有什么建议吗?

3 个答案:

答案 0 :(得分:2)

这里的答案都是正确的。这个没有内置的快捷方式,你需要在while而不是for循环中分开迭代器,以便在调用Enumerator.MoveNext()和使用Enumerator.Current

IEnumerator<Things> iterator = Helpful.GetMoreThings.GetEnumerator();
bool more = true;

while (more) {
    try {
        more = iterator.MoveNext();
    }
    catch (Exception e) {
        //crash, burn
    }

    if (more)
        yield return iterator.Current;
}

答案 1 :(得分:1)

Helpful.GetMoreThings()调用和枚举与yield

分开
try {
    var results = Helpful.GetMoreThings().ToList();
}
catch (Exception e) {
    //crash, burn
}

foreach (Things thing in results)
    yield return thing;

类似的东西。

如果你需要这个懒惰,代码变得非常讨厌。您无法再使用foreach。你需要手动编写迭代循环,代码大小爆炸,就像20行难以辨认的混乱。我知道,因为我昨天这样做了。

答案 2 :(得分:1)

您可以使用HTML5 outline algorithm,也可以只复制the Catch() extension method from Ix.Net。代码可能如下所示:

return Helpful.GetMoreThings().Catch((Exception e) =>
{
    // crash, burn
    return null;
}