【问题标题】:Translation of yield into VB.NET将产量翻译成 VB.NET
【发布时间】:2011-04-18 05:11:52
【问题描述】:

首先我必须假设我对 C# yield 关键字及其功能不是很熟悉。 将其“翻译”成 VB.NET 的最佳/最简单方法是什么? 特别是我试图将this code 转换为VB.NET,但我失败了:

yield return new MatchNode(++index, current.Value);

我拥有的是:

Imports System.Collections
Imports System.Data.SqlTypes
Imports System.Diagnostics.CodeAnalysis
Imports System.Text.RegularExpressions
Imports Microsoft.SqlServer.Server

Class MatchNode
    Private _index As Integer
    Private _value As String

    Public Sub New(ByVal index As Integer, ByVal value As String)
        _index = index
        _value = value
    End Sub

    Public ReadOnly Property Index() As Integer
        Get
            Return _index
        End Get
    End Property

    Public ReadOnly Property Value() As String
        Get
            Return _value
        End Get
    End Property

End Class

Class MatchIterator
    Implements IEnumerable

    Private _regex As Regex
    Private _input As String

    Public Sub New(ByVal input As String, ByVal pattern As String)
        MyBase.New()
        _regex = New Regex(pattern, UserDefinedFunctions.Options)
        _input = input
    End Sub

    Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        Dim index As Integer = 0
        Dim current As Match = Nothing

        While (current Is Nothing OrElse current.Success)
            If current Is Nothing Then
                current = _regex.Match(_input)
            Else
                current = current.NextMatch()
            End If

            If current.Success Then
                index += 1
                'following should be a VB.Net yield'
                Return New MatchNode(index, current.Value)
            End If

        End While
    End Function
End Class

Partial Public Class UserDefinedFunctions

    <SqlFunction(FillRowMethodName:="FillMatchRow", TableDefinition:="[Index] int,[Text] nvarchar(max)")> _
    Public Shared Function RegexMatches(ByVal input As SqlChars, ByVal pattern As SqlString) As IEnumerable
        Return New MatchIterator(New String(input.Value), pattern.Value)
    End Function

    Public Shared Sub FillMatchRow(ByVal data As Object, ByRef index As SqlInt32, ByRef text As SqlChars)
        Dim node As MatchNode = CType(data, MatchNode)
        index = New SqlInt32(node.Index)
        text = New SqlChars(node.Value.ToCharArray)
    End Sub

End Class

【问题讨论】:

标签: c# vb.net ienumerable yield


【解决方案1】:

由于 VB.NET 不提供迭代器块,您将不得不手动编写迭代器类,这非常痛苦。我会尝试(手动)为您用 C# 编写它,这样您就可以明白我的意思了……就像这样:

internal class MatchIterator : IEnumerable
{
    private class MatchEnumerator : IEnumerator
    {
        int index = 0;
        private Match currentMatch;
        private MatchNode current;
        readonly Regex regex;
        readonly string input;
        public MatchEnumerator(Regex regex, string input)
        {
            this.regex = regex;
            this.input = input;
        }
        public object Current { get { return current; } }

        public void Reset() { throw new NotSupportedException(); }
        public bool MoveNext()
        {
            currentMatch = (currentMatch == null) ? regex.Match(input) : currentMatch.NextMatch();
            if (currentMatch.Success)
            {
                current = new MatchNode(++index, currentMatch.Value);
                return true;
            }
            return false;
        }
    }
    private Regex _regex;
    private string _input;

    public MatchIterator(string input, string pattern)
    {
        _regex = new Regex(pattern, UserDefinedFunctions.Options);
        _input = input;
    }

    public IEnumerator GetEnumerator()
    {
        return new MatchEnumerator(_regex, _input);
    }
}

【讨论】:

  • 谢谢。我仍然有一个问题,即 sql-server 使用这个函数总是返回一个空的结果集。但与其花更多时间将 C# 转换为 VB.Net,我将按照 Tim Murphy 的建议将其保留为 C#。
  • 另一种方法是使用GetEnumerator() 方法,该方法创建T[]List&lt;T&gt; 并返回该数组或列表的枚举数。当然,它的语义与惰性求值的语义不同,但它仍然是一个有用的技巧(即使在 C# 中,如果想要枚举集合的快照,这种方法会比复制更好)它到一个数组/列表并使用yield return 来迭代该数组/列表的元素)。
  • 更新 - 他们已经在 VB.NET 版本 11 中添加了迭代器块 msdn.microsoft.com/en-us/library/we86c8x2(v=vs.110).aspx
【解决方案2】:

你必须问自己我真的要编辑这段代码吗?如果答案是否定的或不是非常多,那么不要打扰,将其保留为 C# 代码。

我是一名 VB.NET 开发人员,并且几乎放弃了将 C# 代码从网络转换为 VB.NET。我只是为我转储代码的所需项目提供了一个 C# 库。只有当我发现我需要定期/大量开发代码时,我才会经历将其转换为 VB.NET 的痛苦。

【讨论】:

  • 好点,因为我并不真正需要它作为 VB.Net,而只需要 SQL-Server 中的 dll。
【解决方案3】:

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

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

现在是it's included in .NET 4.5 and VS 2012

【讨论】:

    【解决方案4】:

    如果你真的非常想手动实现迭代器类,我建议先阅读 Jon Skeet 的“c# in depth”的this chapter,以了解 c# 编译器对这个小yield 做了什么 关键字。

    【讨论】:

    • 我希望有一种类似且简单的方法,它的作用几乎相同,但没有完整的产量功能(惰性评估)。
    【解决方案5】:

    Bill McCarthy 在 Visual Studio 杂志上的 nice article 是关于通过实现 IEnumerable(Of T)IEnumerator(Of T) 在 VB.NET 中模拟 yield

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-13
      相关资源
      最近更新 更多