Dopo un coupleshowstoppers migrazione ritardata al runtime .NET 4.6 Mi è stato finalmente comodo passare ai compilatori C# 6/VB14 fino a quando non ho trovato un problema critico con le funzioni iteratore in VB. NET buttando via variabili locali.La funzione Iterator VB.NET perde le variabili locali
Il seguente esempio di codice genera un'eccezione di riferimento null sulla riga commentata quando viene compilata in modalità di rilascio (ottimizzata) 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
Quindi, questo è piuttosto terrificante.
In particolare l'equivalente C# di questo codice viene eseguito senza problemi. Ancora più importante, questo funziona (e ha funzionato) nelle versioni precedenti del compilatore VB. Confrontando MSIL tra la macchina a stati creata dai due diversi compilatori, sembra che il nuovo compilatore utilizzi .locals per la memorizzazione di variabili locali quasi esclusivamente mentre il vecchio compilatore utilizzava campi mutabili sulla macchina a stati per salvare i valori locali.
Mi manca qualcosa? Non sono stato in grado di trovare alcuna documentazione di un cambio di rottura con gli iteratori in VB (né posso immaginare che sarebbe il caso), ma non ho trovato nessun altro che abbia riscontrato questo problema.
Questo particolare esempio può essere risolto spostando la costruzione di map
dopo il primo ciclo foreach, tuttavia la mia preoccupazione è che non ho alcun senso del vero sapore di questo problema. Non sono interessato a modificare il codice per "basta farlo funzionare". In quale altro posto nella nostra ampia base di codice potrei imbattersi in un problema di una stessa vena? Ho inviato il problema su Connect ma spesso mi sembra un buco nero.
UPDATE
Qualcuno ha appena segnalato lo stesso problema con la macchina statale asincrona sulla pagina Roslyn GitHub: https://github.com/dotnet/roslyn/issues/9001
Speriamo che questo comincia a diventare un po 'di attenzione.
Ho eseguito il codice in VS2015, compilato su .NET Framework 4.5.2 e questo produce anche un 'NullReferenceException'. Quindi sembrerebbe non essere isolato in .NET 4.6 runtime. –
Se compilo usando VS2013 contro 4.5.2 o 4.6, non ottengo il 'NullReferenceException'. Quindi, come dici tu, questo è un problema del compilatore, piuttosto che un problema di struttura. –
@Threadcreator: il tuo codice funziona perfettamente per me. Utilizzo di Windows 10 Pro (x64), Visual Studio 2015 Express per Windows Desktop. Materiale di riferimento: 4.5 – SiriSch