2008-10-30 10 views

Antwort

1

Hmm, sieht aus wie Sie out of luck sein könnte:

ich mit einem Problem heute zu kämpfen, als einige C# VB.NET konvertieren. C# hat eine wirklich coole "yield return" -Anweisung, die in einem Iterator-Block verwendet wird, um dem Enumerator-Objekt einen Wert zu geben. VB.NET hat nicht das Schlüsselwort "yield". Also, es gibt ein paar Lösungen (von denen keine wirklich sauber sind), um dies zu umgehen. Sie können eine return-Anweisung verwenden, um den Wert zurückzugeben, wenn Sie eine Schleife durchlaufen und einen Enumerator aufbrechen und einen einzelnen Wert zurückgeben möchten. Wenn Sie jedoch die gesamte Enumeration zurückgeben möchten, erstellen Sie eine List() des untergeordneten Typs und geben Sie die Liste zurück. Da Sie dies normalerweise mit einem IEnumerable verwenden, wird List() gut funktionieren.

dass vor einem Jahr geschrieben wurde, nicht sicher, ob jemand da dann ..

mit irgendetwas anderes besser kommen hat

Edit: diese 11 von VB.NET in der Version möglich sein wird (die nach VS2010), ist die Unterstützung von Iteratoren geplant. Die Spezifikation is available here.

1

C# 'Yield-Schlüsselwort zwingt den Compiler, im Hintergrund einen Zustandsautomaten zu erstellen, der es unterstützt. VB.Net verfügt nicht über das Schlüsselwort yield. Aber es hat ein Konstrukt, mit dem Sie eine Zustandsmaschine innerhalb einer Funktion erstellen können: Static function members.

Es sollte möglich sein, die Auswirkungen einer Rendite-Funktion nachzuahmen, indem eine generische Klasse erstellt wird, die IEnumerable sowie die benötigte Zustandsmaschine implementiert und eine Instanz als statisches Element in die Funktion platziert.

Dies würde natürlich erfordern, dass die Klasse außerhalb der Funktion implementiert wird. Aber wenn es richtig gemacht wird, sollte die Klasse im allgemeinen Fall wiederverwendbar sein. Ich habe jedoch nicht mit der Idee gespielt, irgendwelche Implementierungsdetails bereitzustellen.

+0

Hey Joel, haben Sie diese Idee zumindest jetzt zweimal erwähnt. Lust, deine Idee weiter auszuarbeiten? –

+0

Ich habe das ein wenig genauer untersucht, und ich bin mir nicht mehr sicher, ob Sie die gleiche Art von Zustandsmaschine wie C# 'yield keyword in einer lokalen Variablen von VB.Net Static erzeugen können. Nicht, dass es unmöglich wäre, aber es wäre sicherlich nicht trivial und am Ende müsstest du noch irgendeinen seltsamen Code für die Maschine schreiben. Auch das konnte man in Visual Studio 2005 nicht machen, da es Lambda-Ausdrücke erfordern würde. –

4

Ich bin immer noch mit meinem Kopf um dieses Konzept. Der Artikel Use Iterators in VB Now wurde kürzlich im Visual Studio Magazine veröffentlicht.

+0

Der Link ist kaputt! – Peter

-4

Unten gibt Ausgang: 2, 4, 8, 16, 32

In VB.

NET
Public Shared Function setofNumbers() As Integer() 

    Dim counter As Integer = 0 
    Dim results As New List(Of Integer) 
    Dim result As Integer = 1 
    While counter < 5 
     result = result * 2 
     results.Add(result) 
     counter += 1 
    End While 
    Return results.ToArray() 
End Function 

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load 
    For Each i As Integer In setofNumbers() 
     MessageBox.Show(i) 
    Next 
End Sub 

In C#

private void Form1_Load(object sender, EventArgs e) 
{ 
    foreach (int i in setofNumbers()) 
    { 
     MessageBox.Show(i.ToString()); 
    } 
} 

public static IEnumerable<int> setofNumbers() 
{ 
    int counter=0; 
    //List<int> results = new List<int>(); 
    int result=1; 
    while (counter < 5) 
    { 
     result = result * 2; 
     counter += 1; 
     yield return result; 
    } 
} 
0

Beachten Sie, dass verzögerte Ausführung und lazy evaluation Eigenschaften von LINQ Expresssions und Methoden ermöglichen es uns, effektiv individuelle Iteratoren zu implementieren, bis die yield-Anweisung in .NET 4.5 verfügbar ist. Yield wird intern von LINQ-Ausdrücken und -Methoden verwendet.

Der folgende Code demonstriert dies.

Private Sub AddOrRemoveUsersFromRoles(procName As String, 
             applicationId As Integer, 
             userNames As String(), 
             rolenames As String()) 
    Dim sqldb As SqlDatabase = CType(db, SqlDatabase) 
    Dim command As DbCommand = sqldb.GetStoredProcCommand(procName) 
    Dim record As New SqlDataRecord({New SqlMetaData("value", SqlDbType.VarChar,200)}) 
    Dim setRecord As Func(Of String, SqlDataRecord) = 
     Function(value As String) 
      record.SetString(0, value) 
      Return record 
     End Function 
    Dim userNameRecords As IEnumerable(Of SqlDataRecord) = userNames.Select(setRecord) 
    Dim roleNameRecords As IEnumerable(Of SqlDataRecord) = rolenames.Select(setRecord) 
    With sqldb 
     .AddInParameter(command, "userNames", SqlDbType.Structured, userNameRecords) 
     .AddInParameter(command, "roleNames", SqlDbType.Structured, roleNameRecords) 
     .AddInParameter(command, "applicationId", DbType.Int32, applicationId) 
     .AddInParameter(command, "currentUserName", DbType.String, GetUpdatingUserName) 
     .ExecuteNonQuery(command) 
    End With 
End Sub