After a couple showstoppers 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.
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.
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
So, that's pretty frightening.
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.
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.
This particular example can be worked around by moving the construction of map
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 Connect but that often feels like a black hole.
UPDATE
Someone just reported the same issue with the async state machine on the Roslyn GitHub page: https://github.com/dotnet/roslyn/issues/9001
Hopefully this starts to get a little attention.