Question

    

Cette question a déjà une réponse ici:

    
            
  •              Rendement dans VB.NET                                      8 réponses                          
  •     
    

Comment implémenter le modèle d'itérateur dans VB.NET , qui n'a pas le mot clé rendement ?

Était-ce utile?

La solution

Ceci est maintenant pris en charge dans VS 2010 SP1, avec le CTP Async, voir: Iterators ( C # et Visual Basic) sur MSDN et télécharger Visual Studio Async CTP (Version 3) .

Un code tel que celui-ci fonctionne:

Private Iterator Function SomeNumbers() As IEnumerable
    ' Use multiple yield statements.
    Yield 3
    Yield 5
    Yield 8
End Function

Autres conseils

VB.NET ne prend pas en charge la création d’itérateurs personnalisés et n’a donc pas d’équivalent au mot-clé de rendement C #. Toutefois, vous pouvez consulter l'article de la base de connaissances Comment créer un fichier Visual Basic .NET ou Visual Classe Basic 2005 utilisable dans une instruction For Each pour plus d'informations.

Le mot-clé de rendement de C # oblige le compilateur à créer une machine à états en arrière-plan pour la prendre en charge. VB.Net n'a pas le mot-clé de rendement. Mais il a une construction qui vous permettrait de créer une machine à états dans une fonction: Membres de la fonction statique .

Il devrait être possible d'imiter les effets d'une fonction de retour de rendement en créant une classe générique qui implémente IEnumerable ainsi que la machine à états requise et en plaçant une instance en tant que membre statique dans votre fonction.

Cela nécessiterait bien sûr d’implémenter la classe en dehors de la fonction. Mais si cela est fait correctement, la classe devrait être réutilisable dans le cas général. Je n'ai pas assez joué avec l'idée pour fournir des détails sur la mise en œuvre, cependant.

Hmm, il semblerait que vous soyez par chance :

  

Je rencontrais un problème aujourd'hui lors de la conversion de C # en VB.NET. C # a un très bon " rendement du rendement " instruction utilisée dans un bloc itérateur pour fournir une valeur à l'objet énumérateur. VB.NET ne dispose pas du "rendement". mot-clé. Donc, il existe quelques solutions (aucune n’est vraiment propre) pour résoudre ce problème. Vous pouvez utiliser une instruction return pour renvoyer la valeur si vous parcourez en boucle et souhaitez casser un énumérateur et renvoyer une valeur unique. Toutefois, si vous souhaitez renvoyer l'énumération complète, créez une List () du type enfant et renvoyez la liste. Puisque vous utilisez généralement ceci avec un IEnumerable, List () fonctionnera bien.

Cela a été écrit il y a un an, je ne sais pas si quelqu'un a proposé autre chose de mieux depuis.

Éditer: cela sera possible dans la version 11 de VB.NET (celle après VS2010), un support pour les itérateurs est prévu. La spécification est disponible ici .

N'oubliez pas que les propriétés d'exécution différée et d'évaluation paresseuse des expressions et méthodes LINQ nous permettent d'implémenter efficacement des itérateurs personnalisés jusqu'à ce que l'instruction de rendement soit disponible dans .NET 4.5. Le rendement est utilisé en interne par les expressions et méthodes LINQ.

Le code suivant montre cela.

    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

Ci-dessous donne le résultat: 2, 4, 8, 16, 32

Dans 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

En 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;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top