将yield转换为VB.NET

3

首先,我必须假设我对C# yield关键字及其功能不太熟悉。将其“翻译”成VB.NET的最佳/最简单方法是什么? 特别是我试图将此代码转换为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

1
你看过这个网址吗?https://dev59.com/f3VD5IYBdhLWcg3wE3Xz - abatishchev
请问如何将C#中的yield return转换为VB.NET? - Marc Gravell
我看到了它们,但是我没有弄清楚如何做,错过了一个例子。 - Tim Schmelter
https://dev59.com/oUfRa4cB1Zd3GeqP-p9l - Mauricio Scheffer
5个回答

3

由于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#。 - Tim Schmelter
另一种方法是拥有一个 GetEnumerator() 方法,该方法创建一个 T[]List<T> 并返回该数组或列表的枚举器。当然,这与惰性求值的语义不同,但仍然是一个有用的技巧(即使在 C# 中,如果想要枚举集合的快照,则使用此方法比如将其复制到数组/列表并使用 yield return 迭代该数组/列表的元素更好)。 - supercat
更新 - 他们在VB.NET的11版本中添加了迭代器块。http://msdn.microsoft.com/en-us/library/we86c8x2(v=vs.110).aspx - Austin Thompson

3

3

你必须问自己,我真的要编辑这段代码吗?如果答案是否定的或者不是很需要,那就不必费心了,保留它作为C#代码。

我是一名VB.NET开发人员,几乎放弃了将来自网络的C#代码转换为VB.NET。我有一个C#库,可以将所需项目的代码倒入其中。只有当我发现需要经常/大量开发代码时,我才会经历将其转换为VB.NET的痛苦。


很好,因为我并不真正需要它作为 VB.Net,只需要将其作为 SQL-Server 中的 dll。 - Tim Schmelter

1

如果您真的非常想手动实现迭代器类,我建议您先阅读Jon Skeet的《深入C#》中本章的内容,以了解c#编译器如何处理这个小小的yield关键字。


我希望有一种类似而简单的方法,几乎可以做到相同的事情,但不需要整个yield功能(惰性求值)。 - Tim Schmelter

1

Visual Studio杂志上的Bill McCarthy撰写了一篇不错的文章,介绍如何通过实现IEnumerable(Of T)IEnumerator(Of T)在VB.NET中模拟yield


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接