用于包装抛出API的.NET迭代器

我有一个带有API的类,它允许我询问对象,直到它抛出IndexOutOfBoundsException

我想将它包装到迭代器中,以便能够编写更清晰的代码。 但是,我需要捕获exception以停止迭代:

 static IEnumerable Iterator( ExAPI api ) { try { for( int i = 0; true; ++i ) { yield return api[i]; // will throw eventually } } catch( IndexOutOfBoundsException ) { // expected: end of iteration. } } 

但…

与expression一起使用时,yield return语句不能出现在catch块或具有一个或多个catch子句的try块中。 有关更多信息,请参阅exception处理语句(C#参考).Statements(C#参考)。 (来自msdn )

我怎么还能包装这个api?

您只需将yield return语句移到try块之外,如下所示:

 static IEnumerable Iterator( ExAPI api ) { for( int i = 0; true; ++i ) { object current; try { current = api[i]; } catch(IndexOutOfBoundsException) { yield break; } yield return current; } } 

您可以将获取对象的简单操作包装到单独的函数中。 你可以在那里捕获exception:

 bool TryGetObject( ExAPI api, int idx, out object obj ) { try { obj = api[idx]; return true; } catch( IndexOutOfBoundsException ) { return false; } } 

然后,调用该函数并在必要时终止:

 static IEnumerable Iterator( ExAPI api ) { bool abort = false; for( int i = 0; !abort; ++i ) { object obj; if( TryGetObject( api, i, out obj ) ) { yield return obj; } else { abort = true; } } } 

只需重新排序代码:

 static IEnumerable Iterator( ExAPI api ) { bool exceptionThrown = false; object obj = null; for( int i = 0; true; ++i ) { try { obj = api[i]; } catch( IndexOutOfBoundsException ) { exceptionThrown = true; yield break; } if (!exceptionThrown) { yield return obj; } } } 

如果你根本无法检查对象的边界,你可以做这样的事情

 static IEnumerable Iterator( ExAPI api ) { List output = new List(); try { for( int i = 0; true; ++i ) output.Add(api[i]); } catch( IndexOutOfBoundsException ) { // expected: end of iteration. } return output; } 

虽然我现在看到这里,但我相信上面的答案更好。 一个SLaks发布了。

  static IEnumerable Iterator(ExAPI api) { int i = 0; while (true) { Object a; try { a = api[i++]; } catch (IndexOutOfBoundsException) { yield break; } yield return a; } }