coupleshowstoppersの後、.NET 4.6ランタイムへの移行が遅れました。VBのイテレーター関数で重大な問題が発生するまで、最終的にC#6/VB14コンパイラーに移行するのが快適でした。 NETはローカル変数を投げ捨てる。VB.NETイテレーター機能がローカル変数を失う
次のコード例は、Visual Studio 2015/msbuildでリリースモード(最適化)でコンパイルされたときに、コメント行にnull参照例外をスローします。
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
これはかなり恐ろしいことです。
特に、このコードのC#に相当するものは問題なく実行されます。さらに重要なことは、これはVBコンパイラの以前のバージョンでも動作しており、動作していることです。 2つの異なるコンパイラによって作成されたステートマシン間のMSILを比較すると、新しいコンパイラはローカル変数保存用の.localsをほぼ排他的に使用しているように見えますが、古いコンパイラはローカル値を保存するためにステートマシン上で可変フィールドを使用していました。
何か不足していますか?私はVBでイテレータの改訂に関する文書を見つけることはできませんでしたが、それが当てはまるとは想像できませんでしたが、他の誰かがこの問題にぶつかったことはありませんでした。
この特定の例は、最初のforeachループの後にmap
の構成を移動することで回避できますが、私の懸念は、この問題の真の味がないということです。私はコードを変更して「それを機能させる」ことに興味はありません。私たちの広範なコードベースで、私は同じ問題にぶつかるかもしれませんか?私はConnectに問題を提出しましたが、しばしばブラックホールのように感じます。
UPDATE
誰かがちょうどRoslynのGitHubのページで非同期ステートマシンと同じ問題を報告:https://github.com/dotnet/roslyn/issues/9001
うまくいけば、これは少し注意を取得するために開始します。
.NET Framework 4.5.2に対してコンパイルされたVS2015でコードを実行しましたが、これも 'NullReferenceException'を生成します。したがって、.NET 4.6ランタイムには分離されていないように見えます。 –
4.5.2または4.6に対してVS2013を使ってコンパイルすると、 'NullReferenceException'が出ません。だから、あなたが言うように、これはフレームワークの問題ではなく、コンパイラの問題です。 –
@Threadcreator:あなたのコードは、私にとって完璧に機能します。 Windows 10 Pro(x64)、Windowsデスクトップ用Visual Studio 2015 Expressを使用します。 Targetframework:4.5 – SiriSch