{"id":4674,"date":"2017-03-20T22:15:02","date_gmt":"2017-03-20T22:15:02","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=4674"},"modified":"2017-03-20T22:15:02","modified_gmt":"2017-03-20T22:15:02","slug":"how-does-yield-return-work-in-net","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/how-does-yield-return-work-in-net\/","title":{"rendered":"How does yield return work in .NET"},"content":{"rendered":"<p>A while back I had a chat with somebody who seemed very interested in what the IL code for certain C#\/.NET language features might look like &#8211; whilst it&#8217;s something I did have an interest in during the early days of .NET, it&#8217;s not something I had looked into since then, so it made me interested to take a look again. <\/p>\n<p>One specific language feature of interest was &#8220;what would the IL for <em>yield return<\/em> look like&#8221;. <\/p>\n<p>This is what I found&#8230;<\/p>\n<p>Here&#8217;s a stupidly simple piece of C# code that we&#8217;re going to use. We&#8217;ll generate the binary then decompile it and view the IL etc.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic IEnumerable&lt;string&gt; Get()\r\n{\r\n   yield return &quot;A&quot;;\r\n}\r\n<\/pre>\n<p>Using JetBrains dotPeek (ILDASM, Reflector or ILSpy can ofcourse be used to do generate the IL etc.). So the IL created for the above method looks like this<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n.method public hidebysig instance \r\n   class &#x5B;mscorlib]System.Collections.Generic.IEnumerable`1&lt;string&gt; \r\n      Get() cil managed \r\n{\r\n   .custom instance void  &#x5B;mscorlib]System.Runtime.CompilerServices.IteratorStateMachineAttribute::.ctor(class &#x5B;mscorlib]System.Type) \r\n   = (\r\n      01 00 1b 54 65 73 74 59 69 65 6c 64 2e 50 72 6f \/\/ ...TestYield.Pro\r\n      67 72 61 6d 2b 3c 47 65 74 3e 64 5f 5f 31 00 00 \/\/ gram+&lt;Get&gt;d__1..\r\n      )\r\n   \/\/ MetadataClassType(TestYield.Program+&lt;Get&gt;d__1)\r\n   .maxstack 8\r\n\r\n   IL_0000: ldc.i4.s     -2 \/\/ 0xfe\r\n   IL_0002: newobj       instance void TestYield.Program\/'&lt;Get&gt;d__1'::.ctor(int32)\r\n   IL_0007: dup          \r\n   IL_0008: ldarg.0      \/\/ this\r\n   IL_0009: stfld        class TestYield.Program TestYield.Program\/'&lt;Get&gt;d__1'::'&lt;&gt;4__this'\r\n   IL_000e: ret          \r\n} \/\/ end of method Program::Get\r\n<\/pre>\n<p>If we ignore the IteratorStateMachineAttribute and jump straight to the CIL code label IL_0002 it&#8217;s probably quite obvious (even if you do not know anything about IL) that this is creating a new instance of some type, which appears to be an inner class (within the Program class) named &lt;Get&gt;d__1. The preceeding ldc.i4.s instruction simply pushes an Int32 value onto the stack, in this instance that&#8217;s the value -2. <\/p>\n<p><em>Note: <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.runtime.compilerservices.iteratorstatemachineattribute(v=vs.110).aspx\" target=\"_blank\">IteratorStateMachineAttribute<\/a> expects a Type argument which is the state machine type that&#8217;s generated by the compiler.<\/em><\/p>\n<p>Now I could display the IL for this new type and we could walk through that, but it&#8217;d be much easier viewing some C# equivalent source to get some more readable representation of this. So I got dotPeek to generate the source for this type (from the IL). <\/p>\n<p>First let&#8217;s see what changes are made by the compiler to the Get() method we wrote<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;IteratorStateMachine(typeof (Program.&lt;Get&gt;d__1))]\r\npublic IEnumerable&lt;string&gt; Get()\r\n{\r\n   Program.&lt;Get&gt;d__1 getD1 = new Program.&lt;Get&gt;d__1(-2);\r\n   getD1.&lt;&gt;__this = this;\r\n   return (IEnumerable&lt;string&gt;) getD1;\r\n}\r\n<\/pre>\n<p>You can now see the <em>newobj<\/em> in it&#8217;s C# form, creating the &lt;Get&gt;d__1 object with a ctor argument of -2 which is assigned as an initial state.<\/p>\n<p>Now let&#8217;s look at this lt;Get&gt;d__1 generated code <\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;CompilerGenerated]\r\nprivate sealed class &lt;Get&gt;d__1 : \r\n    IEnumerable&lt;string&gt;, IEnumerable, \r\n    IEnumerator&lt;string&gt;, IDisposable, \r\n    IEnumerator\r\n{\r\n   private int &lt;&gt;1__state;\r\n   private string &lt;&gt;2__current;\r\n   private int &lt;&gt;l__initialThreadId;\r\n   public Program &lt;&gt;4__this;\r\n\r\n   string IEnumerator&lt;string&gt;.Current\r\n   {\r\n      &#x5B;DebuggerHidden] get\r\n      {\r\n         return this.&lt;&gt;2__current;\r\n      }\r\n   }\r\n\r\n   object IEnumerator.Current\r\n   {\r\n      &#x5B;DebuggerHidden] get\r\n      {\r\n         return (object) this.&lt;&gt;2__current;\r\n      }\r\n   }\r\n\r\n   &#x5B;DebuggerHidden]\r\n   public &lt;Get&gt;d__1(int &lt;&gt;1__state)\r\n   {\r\n      base..ctor();\r\n      this.&lt;&gt;1__state = param0;\r\n      this.&lt;&gt;l__initialThreadId = Environment.CurrentManagedThreadId;\r\n   }\r\n\r\n   &#x5B;DebuggerHidden]\r\n   void IDisposable.Dispose()\r\n   {\r\n   }\r\n\r\n   bool IEnumerator.MoveNext()\r\n   {\r\n      switch (this.&lt;&gt;1__state)\r\n      {\r\n         case 0:\r\n            this.&lt;&gt;1__state = -1;\r\n            this.&lt;&gt;2__current = &quot;A&quot;;\r\n            this.&lt;&gt;1__state = 1;\r\n            return true;\r\n          case 1:\r\n            this.&lt;&gt;1__state = -1;\r\n            return false;\r\n          default:\r\n            return false;\r\n      }\r\n   }\r\n\r\n   &#x5B;DebuggerHidden]\r\n   void IEnumerator.Reset()\r\n   {\r\n      throw new NotSupportedException();\r\n   }\r\n\r\n   &#x5B;DebuggerHidden]\r\n   IEnumerator&lt;string&gt; IEnumerable&lt;string&gt;.GetEnumerator()\r\n   {\r\n      Program.&lt;Get&gt;d__1 getD1;\r\n      if (this.&lt;&gt;1__state == -2 &amp;&amp; \r\n          this.&lt;&gt;l__initialThreadId == Environment.CurrentManagedThreadId)\r\n      {\r\n          this.&lt;&gt;1__state = 0;\r\n          getD1 = this;\r\n      }\r\n      else\r\n      {\r\n          getD1 = new Program.&lt;Get&gt;d__1(0);\r\n          getD1.&lt;&gt;4__this = this.&lt;&gt;4__this;\r\n      }\r\n      return (IEnumerator&lt;string&gt;) getD1;\r\n   }\r\n\r\n   &#x5B;DebuggerHidden]\r\n   IEnumerator IEnumerable.GetEnumerator()\r\n   {\r\n      return (IEnumerator) this.System.Collections.Generic.IEnumerable&lt;System.String&gt;.GetEnumerator();\r\n    }\r\n}\r\n<\/pre>\n<p>As you can see, yield causes the compiler to create enumerable implementation for just that one of code.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A while back I had a chat with somebody who seemed very interested in what the IL code for certain C#\/.NET language features might look like &#8211; whilst it&#8217;s something I did have an interest in during the early days of .NET, it&#8217;s not something I had looked into since then, so it made me [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[49,3],"tags":[],"class_list":["post-4674","post","type-post","status-publish","format-standard","hentry","category-net","category-c"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4674","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=4674"}],"version-history":[{"count":11,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4674\/revisions"}],"predecessor-version":[{"id":4706,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/4674\/revisions\/4706"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=4674"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=4674"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=4674"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}