伙计们,我正在尝试将某些东西从C#转换为VB.NET,而我在查找VB.NET中与C#的yield关键字相当的问题时遇到了麻烦。我意识到'yield'不是VB.NET的可转换关键字,所以有人可以告诉我如何在VB.NET中实现这个代码。除了实现的GetEnumerator()函数之外,我将其全部转换过来。它只是一个实现CollectionBase和IEnumerable的类(使LINQ值得):
[Serializable()]
public partial class Customers : CollectionBase, System.Collections.Generic.IEnumerable<BusinessLayer.Customer>
{
public new System.Collections.Generic.IEnumerator<BusinessLayer.Customer> GetEnumerator()
{
foreach (BusinessLayer.Customer Cust in this.List)
{
yield return Cust;
}
}
public Customers()
{
}
public Customers(DataRowCollection datarows) : this()
{
this.Load(datarows);
}
protected void Load(DataRowCollection dataRows)
{
foreach (DataRow dr in dataRows) {
this.Add(new Customer(dr));
}
}
public Customer this[int index] {
get { return (Customer)base.InnerList[index]; }
set { base.InnerList[index] = value; }
}
public int Add(Customer val)
{
return base.InnerList.Add(val);
}
}
提前感谢您的帮助!
答案 0 :(得分:5)
由于您无法使用yield
关键字,因此您必须以另一种方式实施GetEnumerator()
。您可以做的是从List
返回CollectionBase
的枚举器。但是,因为这是IList
而不是IList<T>
,您必须进行投射(您可以使用Linq的Cast<T>()
扩展方法)。然后你的C#代码变为:
public IEnumerator<BusinessLayer.Customer> GetEnumerator()
{
return InnerList.Cast<BusinessLayer.Customer>().GetEnumerator();
}
这给出了相同的结果,但是以略微不同的方式运行(关于不再使用yield
的延迟执行)。
在VB.Net中,GetEnumerator()
将是:
Public Function GetEnumerator() As IEnumerator(Of BusinessLayer.Customer)
Return InnerList.Cast(Of BusinessLayer.Customer)().GetEnumerator()
End Function
其余代码应直接转换为VB.Net。
答案 1 :(得分:1)
要么等待下一版本的VB.NET,要么请参阅Visual Studio杂志中的Bill McCarthy的this nice article。
答案 2 :(得分:0)
我知道你问这个问题已经有一段时间了,但我遇到的问题是VB中没有'yield'关键字。这就是我发现并一直在使用的东西。您可以使用GenericIterator实现'yield',这里是这样一个Iterator的代码:
Public Class GenericIterator(Of T)
Implements IEnumerable(Of T)
Implements IEnumerator(Of T)
Public Delegate Function MoveNextFunc(ByRef nextItem As T) As Boolean
Private _Current As T
Private _func As MoveNextFunc
Public Sub New(ByVal func As MoveNextFunc)
_func = func
End Sub
Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
Return _func(_Current)
End Function
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
Static iBeenCalled As Int32
If (iBeenCalled = 0) AndAlso _
(Threading.Interlocked.Increment(iBeenCalled) = 1) Then
Return Me
Else
Return New GenericIterator(Of T)(_func)
End If
End Function
Public ReadOnly Property Current() As T Implements IEnumerator(Of T).Current
Get
Return _Current
End Get
End Property
Public Overridable Sub Reset() Implements IEnumerator.Reset
Throw New NotImplementedException("Iterator cannot be reset")
End Sub
Private Function IEnumerator_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
Return Me.GetEnumerator
End Function
Private ReadOnly Property IEnumerator_Current() As Object Implements IEnumerator.Current
Get
Return Me.Current
End Get
End Property
Public Sub Dispose() Implements IDisposable.Dispose
' not implemented
End Sub
End Class
有了这个课程,你就可以实现'yield',类似于在这个Zip扩展函数中的完成方式:
Public Module IEnumerableExtensions
<Extension()>
Public Function Zip(Of T1, T2)(ByVal left As IEnumerable(Of T1), ByVal right As IEnumerable(Of T2)) As IEnumerable(Of Pair(Of T1, T2))
Dim leftG As IEnumerator(Of T1) = left.Select(Function(x) x).GetEnumerator()
Dim rightG As IEnumerator(Of T2) = right.Select(Function(x) x).GetEnumerator()
Return New GenericIterator(Of Pair(Of T1, T2)) _
(Function(ByRef x) As Boolean
Dim canMove As Boolean = leftG.MoveNext() AndAlso rightG.MoveNext()
x = New Pair(Of T1, T2)(leftG.Current, rightG.Current)
Return canMove
End Function)
End Function
End Module
lambda函数有一个ref by ref参数,您应该将返回值保存为。
值得注意的是,我在leftG和rightG上调用了选择,因为编译器抱怨像{“foo”,“bar”}这样的IEumebles已经实现了。选择调用自然地删除了实现。
还值得注意的是,要使扩展功能正常工作,您需要导入System.Runtime.CompilerServices
。对于Iterator,您需要System.Collections.Generic
。一般来说,你显然需要System.Linq
。
值得注意的是,在上面的函数中,“Pair”是:
Public Class Pair(Of T1, T2)
Public Property First As T1
Public Property Second As T2
Public Sub New(ByVal f As T1, ByVal s As T2)
First = f
Second = s
End Sub
End Class
我希望这会以某种方式帮助您转换工作!祝你好运!