没关系:
try { Console.WriteLine("Before"); yield return 1; Console.WriteLine("After"); } finally { Console.WriteLine("Done"); }
该finally块在整个事情完成执行时运行(即使枚举在完成之前就被放弃,也IEnumerator<T>支持IDisposable提供一种确保这一点的方法)。
finally
IEnumerator<T>
IDisposable
但这不行:
try { Console.WriteLine("Before"); yield return 1; // error CS1626: Cannot yield a value in the body of a try block with a catch clause Console.WriteLine("After"); } catch (Exception e) { Console.WriteLine(e.Message); }
假设(出于参数考虑)WriteLinetry块中的一个或另一个调用引发了异常。继续执行catch块有什么问题?
WriteLine
catch
当然,收益率返回部分(当前)无法抛出任何东西,但是为什么那应该阻止我们封闭try/ catch处理在a之前或之后抛出的异常yield return呢?
try
yield return
更新: 这里有来自Eric Lippert的有趣评论 -似乎他们已经有足够的问题才能正确实现try / finally行为!
我怀疑这是实际问题,而不是可行性问题。我怀疑很少有这种限制 实际上 是 无法解决 的问题-但是编译器中增加的复杂性将非常重要。
我已经遇到过一些类似的事情:
在每种情况下,都有可能获得更多的自由度,但代价是编译器的额外复杂性。团队做出了务实的选择,为此我称赞他们- 我宁愿使用一种限制性更强的语言,并具有99.9%的准确编译器(是的,有错误;我第二天就碰到了一个)而不是更多灵活的语言,无法正确编译。
编辑:这是一个为什么它可行的伪证明。
考虑到:
现在转换:
try { Console.WriteLine("a"); yield return 10; Console.WriteLine("b"); } catch (Something e) { Console.WriteLine("Catch block"); } Console.WriteLine("Post");
变成(某种伪代码):
case just_before_try_state: try { Console.WriteLine("a"); } catch (Something e) { CatchBlock(); goto case post; } __current = 10; return true; case just_after_yield_return: try { Console.WriteLine("b"); } catch (Something e) { CatchBlock(); } goto case post; case post; Console.WriteLine("Post"); void CatchBlock() { Console.WriteLine("Catch block"); }
唯一的重复是设置try / catch块-但这确实是编译器可以做的。
我可能在这里错过了一些东西-如果是这样,请告诉我!