2008-10-30 13 views

Respuesta

1

Hmm, parece que podría ser out of luck:

yo estaba luchando con un problema hoy al convertir algunos de C# a VB.NET. C# tiene una declaración de "retorno de rendimiento" muy buena que se usa en un bloque de iteradores para proporcionar un valor al objeto del enumerador. VB.NET no tiene la palabra clave "yield". Entonces, hay algunas soluciones (ninguna de las cuales es realmente limpia) para evitar esto. Puede usar una declaración de devolución para devolver el valor si está realizando un bucle y desea dividir un enumerador y devolver un único valor. Sin embargo, si desea devolver la enumeración completa, cree una Lista() del tipo secundario y devuelva la lista. Como usualmente usa esto con un IEnumerable, la Lista() funcionará bien.

que fue escrito hace un año, no está seguro de si alguien ha llegado con cualquier otra cosa mejor desde entonces ..


Editar: esto será posible en la versión 11 de VB.NET (el que está después de VS2010), se planea el soporte para iteradores. La especificación is available here.

1

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

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

Esto, por supuesto, requeriría implementar la clase fuera de la función. Pero si se hace correctamente, la clase debería ser reutilizable en el caso general. Sin embargo, no he jugado con la idea de proporcionar detalles de implementación.

+0

Hola Joel, has mencionado esta idea al menos dos veces. ¿Te apetece dar más cuerpo a tu idea? –

+0

He examinado esto un poco más profundo, y ya no estoy seguro de que pueda crear el mismo tipo de máquina de estados como la palabra clave de cedencia de C# en una variable local estática de VB.Net. No es que sea imposible, pero ciertamente no sería trivial y al final aún tendrías que escribir algunas asignaciones de códigos impares para la máquina. Incluso eso no se podía hacer en Visual Studio 2005, ya que requeriría expresiones lambda. –

4

Todavía estoy entendiendo este concepto también. El artículo Use Iterators in VB Now se publicó recientemente en Visual Studio Magazine.

+0

¡El enlace está roto! – Peter

-4

A continuación da salida: 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; 
    } 
} 
0

Tenga en cuenta que las propiedades de ejecución diferida y evaluación perezosa de expresssions LINQ y métodos nos permiten implementar de manera efectiva iteradores personalizados hasta que la sentencia yield está disponible en .NET 4.5. El rendimiento se usa internamente mediante expresiones y métodos LINQ.

El siguiente código demuestra esto.

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 
Cuestiones relacionadas