VB.NET Iterator Function Loses Local Variables
<p>After a <a href="http://nickcraver.com/blog/2015/07/27/why-you-should-wait-on-dotnet-46/" rel="nofollow">couple</a> <a href="http://blogs.msdn.com/b/maoni/archive/2015/08/12/gen2-free-list-changes-in-clr-4-6-gc.aspx" rel="nofollow">showstoppers</a> delayed migration to the .NET 4.6 runtime I was finally comfortable with moving to the C#6/VB14 compilers until I came across a critical issue with iterator functions in VB.NET throwing away local variables.</p>

<p>The following code example will throw a null reference exception on the commented line when compiled in release mode (optimized) in Visual Studio 2015 / msbuild.</p>

<pre class="lang-vb prettyprint-override"><code>Module Module1

    Sub Main()
        For Each o As Integer In GetAllStuff()
            Console.WriteLine(o.ToString())
        Next

        Console.ReadKey()

    End Sub

    Private Iterator Function GetAllStuff() As IEnumerable(Of Integer)
        Dim map As Dictionary(Of String, String) = New Dictionary(Of String, String)
        Dim tasks As New List(Of Integer)
        tasks.Add(1)

        For Each task As Integer In tasks
            Yield task
        Next

        'The value of map becomes null here under the new VB14 compiler in Release on .NET 4.6'
        For Each s As String In map.Values
            Yield 100
        Next
    End Function

End Module
</code></pre>

<p>So, that's pretty frightening.</p>

<p>Notably the C# equivalent of this code executes without issue.  More importantly, this works (and has worked) under previous versions of the VB compiler.  Comparing the MSIL between the state machine created by the two different compilers, the new compiler appears to be using .locals for local variable storage nearly exclusively while the old compiler was using mutable fields on the state machine for saving off local values.</p>

<p>Am I missing something?  I was not able to find any documentation of a breaking change with iterators in VB (nor can I imagine that would be the case), but also have not found anyone else having hit this issue. </p>

<p>This particular example can be worked around by moving the construction of <code>map</code> to after the first foreach loop, however my concern is that I do not have any sense of the true flavor of this issue.  I'm not interested in modifying code to "just make it work." Where else in our extensive codebase might I run into an issue a same vein?  I have submitted the issue on <a href="https://connect.microsoft.com/VisualStudio/feedback/details/2367811/iterator-locals-lost-in-vb-iterator-method" rel="nofollow">Connect</a> but that often feels like a black hole.</p>

<p><strong>UPDATE</strong></p>

<p>Someone just reported the same issue with the async state machine on the Roslyn GitHub page:  <a href="https://github.com/dotnet/roslyn/issues/9001" rel="nofollow">https://github.com/dotnet/roslyn/issues/9001</a></p>

<p>Hopefully this starts to get a little attention.</p>