【问题标题】:VB.NET equivalent to this C# linq classVB.NET 等价于这个 C# linq 类
【发布时间】:2009-09-25 22:07:15
【问题描述】:

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

提前感谢您的帮助!

【问题讨论】:

  • 如果您告诉他们 Yield 关键字的作用,您可能会从 VB 人员那里获得更多帮助。对于我 35 年运营商的大部分时间,“Yield”意味着一个线程将剩余的 CPU 时间让给调度程序以让任何其他挂起的线程运行。我认为现在 MS 的意思有所不同? (因为有一个简单的、长期存在的 VB 约定)

标签: c# vb.net linq ienumerable


【解决方案1】:

因为您不能使用yield 关键字,您将不得不以另一种方式实现GetEnumerator()。您可以做的是从CollectionBase 返回List 的枚举数。但是,因为这是一个 IList 而不是 IList&lt;T&gt;,所以您必须强制转换它(您可以使用 Linq 的 Cast&lt;T&gt;() 扩展方法)。你的 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。

【讨论】:

    【解决方案2】:

    要么等待下一版本的 VB.NET,要么咨询 Visual Studio 杂志中 Bill McCarthy 的 this nice article

    【讨论】:

      【解决方案3】:

      我知道你问这个问题已经有一段时间了,但我遇到了同样的问题,即在 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
      

      一旦你有了这个类,你就可以像在这个示例 Zip 扩展函数中那样实现“yield”:

      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 函数有一个 by ref 参数,您应该将返回值保存到该参数。

      值得注意的是,我调用了 leftG 和 rightG 上的选择,因为编译器抱怨一些 IEumerables 像 {"foo", "bar"} 已经实现了。选择调用自然地删除了物化。 还值得注意的是,要使扩展功能正常工作,您需要导入System.Runtime.CompilerServices。对于迭代器,您需要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
      

      我希望这对您的转换工作有所帮助!祝你好运!

      【讨论】:

      • 感谢您的回答。不过,阿德里安的回答对我的需要很有用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-05
      • 2011-01-27
      • 1970-01-01
      相关资源
      最近更新 更多