VB.NET相当于这个C#linq类

时间:2009-09-25 22:07:15

标签: c# vb.net linq ienumerable

伙计们,我正在尝试将某些东西从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);
}
}

提前感谢您的帮助!

3 个答案:

答案 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

我希望这会以某种方式帮助您转换工作!祝你好运!