vb.net - observer - state pattern vb net
Patrón iterador en VB.NET(C#usaría rendimiento!) (7)
Esta pregunta ya tiene una respuesta aquí:
- Rendimiento en VB.NET 7 respuestas
¿Cómo implementar el patrón de iterador en VB.NET , que no tiene la palabra clave yield
?
A continuación se muestra la 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
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;
}
}
Esto ahora es compatible con VS 2010 SP1, con Async CTP, consulte: Iteradores (C # y Visual Basic) en MSDN y descargue Visual Studio Async CTP (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
Hmm, parece que no estás de suerte :
Estaba luchando con un problema hoy al convertir 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.
Eso fue escrito hace un año, no estoy seguro si alguien ha encontrado algo mejor desde entonces ...
Editar: esto será posible en la versión 11 de VB.NET (la que está después de VS2010), se planea el soporte para iteradores. La especificación está disponible aquí .
La palabra clave de rendimiento 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: miembros de la función estática .
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 y 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.
Tenga en cuenta que la ejecución diferida y las propiedades de evaluación diferida de las expresiones y los métodos de LINQ nos permiten implementar de manera efectiva iteradores personalizados hasta que la declaración de rendimiento 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
Todavía estoy entendiendo este concepto también. El artículo Use Iterators en VB Now se publicó recientemente en Visual Studio Magazine.
VB.NET no admite la creación de iteradores personalizados y, por lo tanto, no tiene equivalente a la palabra clave de cedencia C #. Sin embargo, es posible que desee consultar el artículo de KB Cómo hacer que una clase de Visual Basic .NET o Visual Basic 2005 se pueda utilizar en una declaración For Each para obtener más información.