{"id":21243,"date":"2008-08-14T10:00:00","date_gmt":"2008-08-14T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/08\/14\/the-implementation-of-iterators-in-c-and-its-consequences-part-3\/"},"modified":"2008-08-14T10:00:00","modified_gmt":"2008-08-14T10:00:00","slug":"the-implementation-of-iterators-in-c-and-its-consequences-part-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20080814-00\/?p=21243","title":{"rendered":"The implementation of iterators in C# and its consequences (part 3)"},"content":{"rendered":"<p><P>\nI mentioned that\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/08\/12\/8849519.aspx\">\nthere was an exception<\/A>\nto the general statement that the conversion of an iterator into\ntraditional C# code is something you could have done yourself.\nThat&#8217;s true, and it was also a pun,\nbecause the exception is exception handling.\n<\/P>\n<P>\nIf you have a <CODE>try &#8230; finally<\/CODE> block in your iterator,\nthe language executes the <CODE>finally<\/CODE> block under the following\nconditions:\n<\/P>\n<UL>\n<LI>After the last statement of the <CODE>try<\/CODE> block is executed.\n    (No surprise here.)\n<LI>When an exception propagates out of the <CODE>try<\/CODE> block.\n    (No surprise here either.)\n<LI>When execution leaves the <CODE>try<\/CODE> block via\n    <CODE>yield break<\/CODE>.\n<LI>When the iterator is <CODE>Dispose<\/CODE>d and the iterator body\n    was trapped inside a <CODE>try<\/CODE> block at the time.\n<\/UL>\n<P>\nThat last case can occur if somebody decides to abandon the enumerator\nbefore it is finished.\n<\/P>\n<PRE>\nIEnumerable&lt;int&gt; CountTo10()\n{\n try {\n  for (int i = 1; i &lt;= 10; i++) {\n   yield return i;\n  }\n } finally {\n  System.Console.WriteLine(&#8220;finally&#8221;);\n }\n}<\/p>\n<p>foreach (int i in CountTo10()) {\n System.Console.WriteLine(i);\n if (i == 5) break;\n}\n<\/PRE>\n<P>\nThis code fragment prints &#8220;1 2 3 4 5 finally&#8221;.\n<\/P>\n<P>\nIf you think about it, this behavior is completely natural.\nYou want the <CODE>finally<\/CODE> block to execute when\nthe <CODE>try<\/CODE> block is finished executing, either by normal\nor abnormal means.\nAlthough control leaves the <CODE>try<\/CODE> block\nduring the <CODE>yield return<\/CODE>, it comes back when\nthe caller asks for the next item from the enumerator, so execution\nof the <CODE>try<\/CODE> block isn&#8217;t finished yet.\nThe <CODE>try<\/CODE> is finished executing after the last statement\ncompletes,\nan exception is thrown past it,\nor execution is abandoned when the enumerator is prematurely destroyed.\n<\/P>\n<P>\nAnd this is exactly what you want when you use the <CODE>finally<\/CODE>\nblock to clean up resources used by the <CODE>try<\/CODE> block.\n<\/P>\n<P>\nNow, technically, you <I>can<\/I> write this yourself without\nusing iterators, but it&#8217;s pretty ugly.\nYou&#8217;ll need more internal state variables to keep track of whether\nthe <CODE>try<\/CODE> block is still active and whether the exit\nof the <CODE>try<\/CODE> block is temporary (due to <CODE>yield return<\/CODE>)\nor permanent.\nIt&#8217;s a real pain in the neck, however, so you probably are better off\nletting the compiler do the work for you.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I mentioned that there was an exception to the general statement that the conversion of an iterator into traditional C# code is something you could have done yourself. That&#8217;s true, and it was also a pun, because the exception is exception handling. If you have a try &#8230; finally block in your iterator, the language [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-21243","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>I mentioned that there was an exception to the general statement that the conversion of an iterator into traditional C# code is something you could have done yourself. That&#8217;s true, and it was also a pun, because the exception is exception handling. If you have a try &#8230; finally block in your iterator, the language [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21243","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=21243"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21243\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=21243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=21243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=21243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}