使用 yield 时,在 try/catch 中包装对迭代器的调用
本文关键字:包装 迭代器 调用 catch yield try 使用 | 更新日期: 2023-09-27 18:34:15
我需要在我作为迭代器实现的方法中做一些繁重的、有点脆弱的逻辑(使用 yield
):
public IEnumerable<Things> GetMoreThings() {
while (goodStuffHappens()) {
Things moreThingsIWant = TemptFateAgain();
if (moreThingsIWant.Any())
yield return moreThingsIWant;
}
}
在调用方法中,我需要将调用包装在 try
/catch
中GetMoreThings
并yield return
结果:
try {
foreach (Things thing in Helpful.GetMoreThings())
yield return thing;
}
catch (Exception e) {
//crash, burn
}
发起者会立即意识到这是不可能的 - try
/catch
块内没有收益这样的东西(只有 try
/finally
)。
有什么建议吗?
这里的两个答案都是正确的。这个没有内置的快捷方式,您需要在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;
}
将Helpful.GetMoreThings()
调用和枚举与yield
分开:
try {
var results = Helpful.GetMoreThings().ToList();
}
catch (Exception e) {
//crash, burn
}
foreach (Things thing in results)
yield return thing;
类似的东西。
如果你需要这个懒惰,代码会变得非常讨厌。您不能再使用 foreach
.您需要手动编写迭代循环,代码大小会爆炸到20行难以辨认的混乱。我知道,因为我昨天做了这件事。
您可以使用 Ix.Net 中的 Catch()
扩展方法,或者只复制其 Apache 许可的源代码。代码可能如下所示:
return Helpful.GetMoreThings().Catch((Exception e) =>
{
// crash, burn
return null;
}