2009-09-25 3 views
1

얘들 아, C#에서 VB.NET으로 변환하려고하는데 VB.NET에서 equivlent를 C#의 yield 키워드로 찾는 데 문제가있다. 나는 'yield'가 VB.NET에 변환 가능한 키워드가 아니라는 것을 알기 때문에 VB.NET에서이 코드를 구현하는 방법을 보여줄 수 있습니까? 나는 구현 된 GetEnumerator() 함수를 제외하고 모든 것을 변환했다. 사전에 어떤 도움이 C# linq 클래스와 동일한 VB.NET

[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); 
} 
} 

감사합니다 : 그것은 단순히 CollectionBase에와 IEnumerable을가합니다 (LINQ 가치가 있도록)를 구현하는 클래스입니다!

+0

VB 사용자가 Yield 키워드의 의미를 알면 VB에서 도움을 얻을 수 있습니다. 내 35 년 캐리어의 "Yield"의 대부분은 다른 보류중인 스레드가 실행될 수 있도록 스케쥴러에 CPU 시간을 남기는 스레드를 의미합니다. 나는 지금 MS가 뭔가 다른 것을 의미한다고 생각하니?(그 때문에 간단하고 오랜 VB 협약이 있기 때문에) – RBarryYoung

+0

http://stackoverflow.com/questions/97381/yield-in-vb-net –

답변

5

yield 키워드를 사용할 수 없기 때문에 GetEnumerator()을 다른 방법으로 구현해야합니다. 할 수있는 일은 List의 열거자를 CollectionBase에서 반환하는 것입니다. 그러나 IList이고 IList<T>이 아니기 때문에이를 캐스팅해야합니다 (이 경우 Linq의 Cast<T>() 확장 방법을 사용할 수 있음).

public IEnumerator<BusinessLayer.Customer> GetEnumerator() 
{ 
    return InnerList.Cast<BusinessLayer.Customer>().GetEnumerator(); 
} 

이 같은 결과를 제공하지만, (더 이상 yield의 지연 실행을 사용에 관련하여)을 약간 다른 방식으로 동작 : 귀하의 C# 코드는된다. VB.Net에서

, GetEnumerator()은 다음과 같습니다 코드의

Public Function GetEnumerator() As IEnumerator(Of BusinessLayer.Customer) 
    Return InnerList.Cast(Of BusinessLayer.Customer)().GetEnumerator() 
End Function 

나머지는 VB.Net로 직접 변환한다.

+0

Adrian에게 감사드립니다. 이것은 작동하는 것처럼 보입니다! – Icemanind

1

VB.NET의 다음 버전을 기다리거나 Visual Studio 매거진의 Bill McCarthy가 this nice article과 상담하십시오.

0

나는 질문을 한 지 오래되었다는 것을 알고 있지만, VB에서 'yield'키워드가없는 것과 같은 문제가있었습니다. 이것은 제가 대신 사용했던 것으로 나타났습니다. 현재 이러한 반복자에 대한 코드하는 GenericIterator와 '항복'을 구현할 수 있습니다

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 

당신은 당신이 구현이이 샘플 우편 확장 기능에 어떻게하는지와 유사한 '수율'수이 클래스가 있으면 :

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 

람다 함수에는 반환 값을 저장해야하는 ref by single 매개 변수가 있습니다.

컴파일러가 { "foo", "bar"}와 같은 일부 IEumerables가 이미 구체화 된 방법에 대해 불평했기 때문에 leftG 및 rightG에서 선택 항목을 호출한다는 점은 주목할 가치가 있습니다. select 호출은 자연스럽게 materialization을 제거합니다. 확장 기능이 제대로 작동하려면 System.Runtime.CompilerServices을 가져와야합니다. 반복기의 경우 System.Collections.Generic이 필요합니다. 그리고 일반적으로 System.Linq이 분명히 필요합니다. 는 위의 함수 '페어'에 있음을 주목할 가치가있다 :이 어떤 식 으로든 전환 노력에 도움이되기를 바랍니다

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 

! 행운을 빕니다!

+0

답을 고맙게 생각합니다. 애드리안의 대답은 내가 필요한 것을 위해 일했습니다. – Icemanind

+0

쿨, 다 잘되어서 기쁩니다. – diceguyd30

관련 문제