2010-09-28 99 views
3

首先,我必须假设我对C#yield关键字及其函数不是很熟悉。 什么是将其“翻译”成VB.NET的最佳/最简单的方法? 尤其是我试图this code转换成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

你见过这个http://stackoverflow.com/questions/97381/yield-in-vb-net? – abatishchev 2010-09-28 09:56:54

+0

http://stackoverflow.com/questions/1145214/c-to-vb-net-yield-return-conversion? – 2010-09-28 09:57:18

+0

我看到了他们,但我没有解决如何做到这一点,错过了一个例子。 – 2010-09-28 10:04:36

回答

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); 
    } 
} 
+0

谢谢。我仍然有问题,sql-server总是返回一个带有这个函数的空结果集。但与其花费更多时间将C#转换为VB.Net,我会遵循Tim Murphy的建议将其保留为C#。 – 2010-09-28 11:50:52

+0

另一种方法是使用'GetEnumerator()'方法创建一个'T []'或'List '并返回该数组或列表的枚举器。当然,这个语义与懒惰评估的语义不同,但它仍然是一个有用的技巧(即使在C#中,如果想枚举集合的快照,这种方法会比复制它到一个数组/列表并使用'yield return'来迭代该数组/列表的元素)。 – supercat 2012-06-25 15:45:33

+0

更新 - 他们已经在版本11中添加了迭代器块到VB.NET http://msdn.microsoft.com/en-us/library/we86c8x2(v=vs.110).aspx – 2014-10-23 12:47:49

1

如果你真的想要实现手工迭代器类,我推荐阅读Jon Skeet编写的“c#in depth”的this chapter,以了解c#编译器用这个小小的收益率产生的关键字。

+0

我希望会有一个类似和简单的方法几乎相同,但没有完整的收益率功能(懒惰评估)。 – 2010-09-28 10:09:04

3

你必须问自己我是否真的要编辑这段代码?如果答案不是或者不是很多,那么不要打扰,把它作为C#代码。

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

+0

好点,因为我不是真的需要它作为VB.Net,但只有SQL Server中的DLL。 – 2010-09-28 11:35:10

1

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