更新时间:2022-10-14 22:08:49
由于VB.NET不提供迭代器块,你将不得不手工编写的迭代器类,这是非常痛苦的。我会尽量把它(手动)在C#中为你写的,所以你可以看到我的意思......像这样:
内部类MatchIterator:IEnumerable的
{
私有类MatchEnumerator:IEnumerator的
{
INT指数= 0;
私人匹配currentMatch;
私人MatchNode电流;
只读正则表达式的正则表达式;
只读字符串输入;
公共MatchEnumerator(正则表达式的正则表达式,字符串输入)
{
this.regex =正则表达式;
this.input =输入;
}
公共对象当前{{返回电流; }}
公共无效复位(){抛出新NotSupportedException异常(); }
公共BOOL的MoveNext()
{
currentMatch =(currentMatch == NULL)? regex.Match(输入):currentMatch.NextMatch();
如果(currentMatch.Success)
{
电流=新MatchNode(++指数,currentMatch.Value);
返回真;
}
返回FALSE;
}
}
私人正则表达式_regex;
私人字符串_Input;
公共MatchIterator(字符串输入,字符串模式)
{
_regex =新的正则表达式(模式,UserDefinedFunctions.Options);
_Input =输入;
}
公众的IEnumerator的GetEnumerator()
{
返回新MatchEnumerator(_regex,_Input);
}
}
first i must assume that i'm not very familiar with the C# yield keyword and its function. What is the best/easiest way to "translate" it into VB.NET? Especially i tried to convert this code into VB.NET, but i failed with:
yield return new MatchNode(++index, current.Value);
What i have is:
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
Since VB.NET doesn't provide iterator blocks, you will have to write the iterator class by hand, which is extremely painful. I'll try to write it (manually) in C# for you, so you can see what I mean... like so:
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);
}
}