VB.NET中的产量

时间:2008-09-18 21:53:22

标签: .net vb.net

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

yield关键字会强制编译器在后台进行一些编码。 The implementation of iterators in C# and its consequences (part 1) 就是一个很好的例子。

8 个答案:

答案 0 :(得分:71)

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

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

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

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

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

我对Yield的关注不够自己尝试,但它应该可行。也就是说,它也远非微不足道,因为C#团队成员Eric Lippert称之为“the most complicated transformation in the compiler”。

自从我在一年前写完第一稿以来,我已经开始相信,在Visual Studio 2010问世之前,它不可能以一种有意义的方式实现,因为它需要向Iterator类发送多个lambda,所以要真正实用,我们需要.NET 4对多行lambda的支持。

答案 1 :(得分:21)

Async CTP包括对VB.NET中Yield的支持。

有关使用情况的信息,请参阅Iterators in Visual Basic

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

答案 2 :(得分:14)

在Visual Studio Magazine中,Bill McCarthy在VB.NET中模拟yield时有一篇很好的文章 Use Iterators in VB Now 。或者等待下一版本的Visual Basic。

答案 3 :(得分:3)

幸运的是,现在我们已经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

这就是我如何从外部提取所有属性:

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

答案 4 :(得分:1)

我个人只是编写自己的迭代器类,它继承自IEnumerator(Of T)。它确实需要一段时间才能做到正确,但我认为最终写它是正确的,然后尽量避免它。我做的另一个方法是编写一个返回IEnumerable(Of T)的递归方法,只返回List(Of T)并使用.AddRange。

答案 5 :(得分:0)

希望这对即将推出的VB版本来说已成为过去。由于迭代器实际上对于新范例(特别是LINQ与惰性评估相结合)非常重要,因此就保守维克的博客而言,这具有相当高的优先级。再说一次,Paul不再是VB团队的负责人,我还没来得及观看PCD会谈。

尽管如此,如果您感兴趣,它们会在Paul's blog中链接。

答案 6 :(得分:0)

以下代码给出了输出

2,4,8,16,32

在VB.NET中,

Public Shared Function setofNumbers() As Integer()
    Dim counter As Integer = 0
    Dim results As New List(Of Integer)
    Dim result As Integer = 1
    While counter < 5
        result = result * 2
        results.Add(result)
        counter += 1
    End While
    Return results.ToArray()
End Function

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    For Each i As Integer In setofNumbers()
        MessageBox.Show(i)
    Next
End Sub

在C#中

private void Form1_Load(object sender, EventArgs e)
{
    foreach (int i in setofNumbers())
    {
        MessageBox.Show(i.ToString());
    }
}

public static IEnumerable<int> setofNumbers()
{
    int counter=0;
    int result=1;
    while (counter < 5)
    {
        result = result * 2;
        counter += 1;
        yield return result;
    }
}

答案 7 :(得分:0)

VB.NET具有Iterator关键字https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator

自Visual Studio 2012以来似乎