Nach einer couple verzögerten Migration auf die .NET 4.6-Laufzeit war ich endlich mit der Umstellung auf die C# 6/VB14-Compiler bequem, bis ich ein kritisches Problem mit Iterator-Funktionen in VB stieß. NET verworfen lokale Variablen.VB.NET Iterator-Funktion verliert lokale Variablen
Im folgenden Codebeispiel wird eine NULL-Verweisausnahme für die Kommentarzeile ausgegeben, wenn sie in Visual Studio 2015/msbuild im Freigabemodus (optimiert) kompiliert wurde.
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
Also, das ist ziemlich beängstigend.
Insbesondere das C# -Aquivalent dieses Codes wird ohne Problem ausgeführt. Noch wichtiger ist, dass dies unter früheren Versionen des VB-Compilers funktioniert (und auch funktioniert hat). Beim Vergleich der MSIL zwischen der von den beiden verschiedenen Compilern erzeugten Zustandsmaschine scheint der neue Compiler fast ausschließlich .locals für den lokalen Variablenspeicher zu verwenden, während der alte Compiler veränderbare Felder auf der Zustandsmaschine zum Speichern lokaler Werte verwendete.
Fehle ich etwas? Ich konnte keine Dokumentation einer brechenden Änderung mit Iteratoren in VB finden (ich kann mir auch nicht vorstellen, dass dies der Fall wäre), aber ich habe auch niemanden gefunden, der dieses Problem gelöst hat.
Dieses spezielle Beispiel kann durch Verschieben der Konstruktion von map
nach der ersten foreach-Schleife gearbeitet werden, aber meine Sorge ist, dass ich keinen Sinn für den wahren Geschmack dieses Problems habe. Ich bin nicht daran interessiert, den Code so zu ändern, dass er einfach funktioniert. Wo sonst in unserer umfangreichen Codebasis könnte ich auf ein Problem stoßen? Ich habe das Problem unter Connect eingereicht, aber das fühlt sich oft wie ein schwarzes Loch an.
UPDATE
Jemand berichtet nur das gleiche Problem mit der Asynchron-Zustandsmaschine auf der Roslyn GitHub Seite: https://github.com/dotnet/roslyn/issues/9001
Hoffentlich beginnt ein wenig Aufmerksamkeit zu bekommen.
Ich habe Ihren Code in VS2015 ausgeführt, gegen .NET Framework 4.5.2 kompiliert und dies erzeugt auch eine 'NullReferenceException'. Es scheint also, es ist nicht isoliert zu .NET 4.6 Runtime. –
Wenn ich mit VS2013 gegen 4.5.2 oder 4.6 kompiliere, bekomme ich die 'NullReferenceException' nicht. Also, wie du sagst, ist das ein Compiler-Problem und kein Framework-Problem. –
@Threadcreator: Dein Code funktioniert perfekt für mich. Verwenden von Windows 10 Pro (x64), Visual Studio 2015 Express für Windows Desktop. Targetframework: 4.5 – SiriSch