VB.NET中的产量

Mag*_*Kat 62 .net vb.net

C#有一个名为yield的关键字.VB.NET缺少这个关键字.Visual Basic程序员如何解决缺少此关键字的问题?他们是否实现了自己的迭代器类?或者他们尝试编码以避免需要迭代器?

产量关键字不强制编译器做幕后的一些编码.在C#中实现迭代器及其后果(第1部分)就是一个很好的例子.

Joe*_*orn 71

注意:这个答案现在已经过时了.之后,Iterator块被添加到VB.NET中

C#在编译时将yield关键字转换为状态机.VB.NET没有yield关键字,但它确实有自己的机制,可以在C#中不容易获得的函数中安全地嵌入状态.

C#static关键字通常使用Shared关键字转换为Visual Basic ,但有两个地方让事情变得混乱.一个是C#静态类实际上是Visual Basic中的模块而不是Shared类(您认为它们允许您在Visual Basic中以任何方式编写代码,但是noooo).另一个是VB.NET确实有自己的Static关键字.但是,Static在VB.NET中有不同的含义.

您可以Static在VB.NET中使用关键字在函数内声明变量,当您执行变量时,它会在函数调用中保留其状态.这与在C#中声明私有静态类成员不同,因为VB.NET中的静态函数成员也保证是线程安全的,因为编译器将其转换为在编译时使用Monitor类.

那么为什么要写这一切呢?那么,应该可以构建一个可重用的泛型Iterator<T>类(或Iterator(Of T)在VB.NET中).在这个类中,您将实现C#使用的状态机,以及Yield()Break()C#关键字对应的方法.然后你可以在一个函数中使用一个静态实例(在VB.NET意义上),这样它最终可以yield在大约相同数量的代码中完成与C#相同的工作(丢弃类实现本身,因为它将是无限的可重复使用的).

关于Yield我不太关心自己尝试它,但它应该是可行的.也就是说,它也远非微不足道,因为C#团队成员Eric Lippert称这是" 编译器中最复杂的转换 ".

自从我在一年前编写第一稿之后,我也开始相信,在Visual Studio 2010问世之前,它不可能以一种有意义的方式实现,因为它需要将多个lambdas发送到Iterator类,所以要真的实际上我们需要.NET 4支持多行lambdas.


Cod*_*nis 21

异步CTP包括用于支持Yield在VB.NET.

有关用法的信息,请参阅Visual Basic中的迭代器.

现在它已包含在Visual Studio 2012的包装盒中!


Mar*_*rkJ 14

在Visual Studio杂志中的Bill McCarthy 在VB.NET中进行模拟时,有很好的文章使用VB中的Iteratorsyield.或者等待下一版本的Visual Basic.


jon*_*ana 5

幸运的是,现在我们已经Yield返回了
我的项目中的一个示例+实现了带有System.Collections.Generic.IEnumerable(T)函数的接口:

Public Class Status
    Implements IStatus

    Private _statusChangeDate As DateTime
    Public Property statusChangeDate As DateTime Implements IStatus.statusChangeDate
        Get
            Return _statusChangeDate
        End Get
        Set(value As Date)
            _statusChangeDate = value
        End Set
    End Property

    Private _statusId As Integer
    Public Property statusId As Integer Implements IStatus.statusId
        Get
            Return _statusId
        End Get
        Set(value As Integer)
            _statusId = value
        End Set
    End Property

    Private _statusName As String
    Public Property statusName As String Implements IStatus.statusName
        Get
            Return _statusName
        End Get
        Set(value As String)
            _statusName = value
        End Set
    End Property

    Public Iterator Function GetEnumerator() As IEnumerable(Of Object) Implements IStatus.GetEnumerator
        Yield Convert.ToDateTime(statusChangeDate)
        Yield Convert.ToInt32(statusId)
        Yield statusName.ToString()
    End Function

End Class

Public Interface IStatus
    Property statusChangeDate As DateTime
    Property statusId As Integer
    Property statusName As String
    Function GetEnumerator() As System.Collections.Generic.IEnumerable(Of Object)
End Interface
Run Code Online (Sandbox Code Playgroud)

这就是我从外部提取所有属性的方法:

For Each itm As SLA.IStatus In outputlist
    For Each it As Object In itm.GetEnumerator()
        Debug.Write(it & " ")
    Next
    Debug.WriteLine("")
Next
Run Code Online (Sandbox Code Playgroud)


Mag*_*Kat 1

我个人只是编写自己的继承自IEnumerator(Of T). 确实需要一些时间才能把它写好,但我认为最终最好把它写好,然后尽量避免它。我所做的另一种方法是编写一个返回IEnumerable(Of T)并且仅返回List(Of T)并使用的递归方法.AddRange