Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

    
            
  •              Rendimiento en VB.NET                                      8 respuestas                          
  •     
    

¿Cómo implementar el patrón de iterador en VB.NET , que no tiene ¿La palabra clave yield ?

¿Fue útil?

Solución

Esto ahora es compatible con VS 2010 SP1, con el CTP asíncrono, ver: Iteradores ( C # y Visual Basic) en MSDN y descargue Visual Studio CTP asíncrono (versión 3) .

Código como este, funciona:

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

Otros consejos

VB.NET no admite la creación de iteradores personalizados y, por lo tanto, no tiene un equivalente a la palabra clave de rendimiento de C #. Sin embargo, es posible que desee consultar el artículo de la KB Cómo crear un Visual Basic .NET o Visual Clase básica de 2005 que se puede usar en una declaración de For Each para obtener más información.

La palabra clave de rendimiento de

C # obliga al compilador a crear una máquina de estados en segundo plano para admitirla. VB.Net no tiene la palabra clave de rendimiento. Pero tiene una construcción que le permitiría crear una máquina de estado dentro de una función: Miembros de función estática .

Debería ser posible imitar los efectos de una función de rendimiento de rendimiento creando una clase genérica que implemente IEnumerable así como la máquina de estado necesaria y colocando una instancia como miembro estático dentro de su función.

Por supuesto, esto requeriría implementar la clase fuera de la función. Pero si se hace correctamente, la clase debe ser reutilizable en el caso general. Sin embargo, no he jugado con la idea lo suficiente como para proporcionar detalles de implementación.

Hmm, parece que podrías ser sin suerte :

  

Hoy tuve problemas con un problema al convertir C # a VB.NET. C # tiene una muy buena " rendimiento de rendimiento " declaración que se utiliza en un bloque de iteradores para proporcionar un valor al objeto del enumerador. VB.NET no tiene el " rendimiento " palabra clave. Por lo tanto, hay algunas soluciones (ninguna de las cuales son realmente limpias) para solucionar esto. Podría usar una declaración de retorno para devolver el valor si está realizando un ciclo continuo y desea romper un enumerador y devolver un solo valor. Sin embargo, si desea devolver la enumeración completa, cree una Lista () del tipo secundario y devuelva la lista. Ya que usualmente usas esto con un IEnumerable, la Lista () funcionará bien.

Eso fue escrito hace un año, no estoy seguro de que alguien haya encontrado algo mejor desde entonces ...


Editar: esto será posible en la versión 11 de VB.NET (la posterior a VS2010), se planea el soporte para los iteradores. La especificación está disponible aquí .

Tenga en cuenta que las propiedades de ejecución diferida y evaluación perezosa de las expresiones y métodos de LINQ nos permiten implementar iteradores personalizados de manera efectiva hasta que la declaración de rendimiento esté disponible en .NET 4.5. El rendimiento es utilizado internamente por los métodos y expresiones LINQ.

El siguiente código lo demuestra.

    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

A continuación se muestra el resultado: 2, 4, 8, 16, 32

En 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;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top