gpt4 book ai didi

.net - VB.NET迭代器函数丢失局部变量

转载 作者:行者123 更新时间:2023-12-04 04:37:41 25 4
gpt4 key购买 nike

couple showstoppers延迟迁移到.NET 4.6运行时之后,我终于适应了C#6/VB14编译器,直到遇到VB.NET中迭代器函数丢弃局部变量的关键问题。

在Visual Studio 2015/msbuild中以 Release模式(优化)进行编译时,以下代码示例将在注释行上引发空引用异常。

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编译器的早期版本下有效(并且已经有效)。比较两个不同编译器创建的状态机之间的MSIL,新编译器似乎几乎只使用.locals来存储本地变量,而旧编译器则使用状态机上的可变字段来保存本地值。

我想念什么吗?我无法在VB中找到有关迭代器的重大更改的任何文档(我也无法想象会是这种情况),但是也找不到其他人遇到此问题。

可以通过将 map的构造移至第一个foreach循环之后来解决此特定示例,但是我担心的是,我对这个问题的真正含义没有任何了解。我对修改代码以使其“正常工作”不感兴趣。在我们广泛的代码库中的其他地方,我可能会遇到同样的问题吗?我已在 Connect上提交了此问题,但通常感觉就像是一个黑洞。

更新

有人刚刚在Roslyn GitHub页面上报告了异步状态机的相同问题: https://github.com/dotnet/roslyn/issues/9001

希望这开始引起一点注意。

最佳答案

首先,感谢您对我在罗斯林团队提出的问题给予了一定的关注。

我从https://github.com/dotnet/roslyn(主分支)中提取了最新的Roslyn源,并向BasicCompilerEmitTest项目添加了一个额外的单元测试,如下所示:

Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests

Public Class KirillsTests
Inherits BasicTestBase

<Fact>
Public Sub IteratorVariableCaptureTest()
Dim source =
<compilation name="Iterators">
<file name="a.vb">
Imports System
Imports System.Collections.Generic

Module Module1

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

Console.WriteLine("done")
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
</file>
</compilation>

Dim expectedOutput = <![CDATA[1
done]]>

Dim compilation = CompilationUtils.CreateCompilationWithReferences(source, references:=LatestVbReferences, options:=TestOptions.DebugExe)
CompileAndVerify(compilation, expectedOutput:=expectedOutput)
CompileAndVerify(compilation.WithOptions(TestOptions.ReleaseExe), expectedOutput:=expectedOutput)
End Sub

End Class

由于 XElementXCData的使用,这看起来像是一团困惑的困惑,但这是其他Roslyn单元测试使用的格式。

我仅对您在问题中发布的代码进行了一种更改-将 Console.ReadKey()替换为 Console.WriteLine("done"),以便我可以跟踪成功完成的情况(因为 CompileAndVerify完全忽略了异常)。

上面的测试通过了。访问 NullReferenceException时没有 map.Values,输出为:

1个
完毕

...如预期的那样。因此,看来您的错误已得到修复-尽管无法确定该修复程序是否随Visual Studio 2015 Update 2一起提供。

async variable capture issue已由 pull request #7693修复,但是 DataFlowPass.SetSlotUnassigned自那时以来已被重写(分为2个方法并进行了修改),因此我无法确认您发现的迭代器问题是否已由该特定的请求请求或其他一些代码更改解决了。

关于.net - VB.NET迭代器函数丢失局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35568392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com