Rendimiento en VB.NET
(8)
Nota: Esta respuesta es vieja ahora. Desde entonces se han agregado bloques Iterator a VB.NET
C # traduce la palabra clave yield en una máquina de estados en tiempo de compilación. VB.NET no tiene la palabra clave yield, pero sí tiene su propio mecanismo para incrustar de manera segura el estado dentro de una función que no está fácilmente disponible en C #.
La palabra clave static
C # normalmente se traduce a Visual Basic utilizando la palabra clave Shared
, pero hay dos lugares donde las cosas se confunden. Una es que una clase estática de C # es realmente un Módulo en Visual Basic en lugar de una clase Compartida (uno pensaría que le dejarían codificar de cualquier manera en Visual Basic, pero noooo). La otra es que VB.NET tiene su propia palabra clave Static
. Sin embargo, Static
tiene un significado diferente en VB.NET.
Utiliza la palabra clave Static
en VB.NET para declarar una variable dentro de una función, y cuando lo hace, la variable conserva su estado en todas las llamadas a funciones. Esto es diferente a simplemente declarar un miembro de clase estática privada en C #, porque se garantiza que un miembro de función estática en VB.NET también será seguro para subprocesos, ya que el compilador lo traduce para usar la clase Monitor en tiempo de compilación.
Entonces, ¿por qué escribir todo esto aquí? Bueno, debería ser posible construir una clase Iterator<T>
genérica reutilizable (o Iterator(Of T)
en VB.NET). En esta clase, implementaría la máquina de estado utilizada por C #, con los métodos Yield()
y Break()
que corresponden a las palabras clave C #. Entonces podría usar una instancia estática (en el sentido VB.NET) en una función para que finalmente pueda hacer casi el mismo trabajo que el yield
C # en aproximadamente la misma cantidad de código (descartando la implementación de la clase en sí misma, ya que sería infinitamente reutilizable).
No me ha importado lo suficiente sobre el rendimiento para intentarlo, pero debería ser factible. Dicho esto, tampoco es trivial, ya que Eric Lippert, miembro del equipo de C #, lo llama " la transformación más complicada del compilador ".
También he llegado a la conclusión desde que escribí el primer borrador de esto hace más de un año que no es realmente posible de una manera significativa hasta que sale Visual Studio 2010, ya que requeriría enviar múltiples lambdas a la clase Iterator y así ser realmente práctico, necesitamos el soporte de .NET 4 para lambdas de múltiples líneas.
C # tiene la palabra clave llamada yield . VB.NET carece de esta palabra clave. ¿Cómo han solucionado los programadores de Visual Basic la falta de esta palabra clave? ¿Implementan ellos poseen clase de iterador? ¿O intentan codificar para evitar la necesidad de un iterador?
La palabra clave yield obliga al compilador a hacer algo de código detrás de escena. La implementación de iteradores en C # y sus consecuencias (parte 1) tiene un buen ejemplo de eso.
Afortunadamente ahora tenemos retorno de Yield
aquí hay un ejemplo de mi proyecto + implementación de una interfaz con la función System.Collections.Generic.IEnumerable(T)
:
Public Class Status
Implements IStatus
Private _statusChangeDate As DateTime
Public Property statusChangeDate As DateTime Implements IStatus.statusChangeDate
Get
Return _statusChangeDate
End Get
Set(value As Date)
_statusChangeDate = value
End Set
End Property
Private _statusId As Integer
Public Property statusId As Integer Implements IStatus.statusId
Get
Return _statusId
End Get
Set(value As Integer)
_statusId = value
End Set
End Property
Private _statusName As String
Public Property statusName As String Implements IStatus.statusName
Get
Return _statusName
End Get
Set(value As String)
_statusName = value
End Set
End Property
Public Iterator Function GetEnumerator() As IEnumerable(Of Object) Implements IStatus.GetEnumerator
Yield Convert.ToDateTime(statusChangeDate)
Yield Convert.ToInt32(statusId)
Yield statusName.ToString()
End Function
End Class
Public Interface IStatus
Property statusChangeDate As DateTime
Property statusId As Integer
Property statusName As String
Function GetEnumerator() As System.Collections.Generic.IEnumerable(Of Object)
End Interface
Así es como extraigo todas las propiedades del exterior:
For Each itm As SLA.IStatus In outputlist
For Each it As Object In itm.GetEnumerator()
Debug.Write(it & " ")
Next
Debug.WriteLine("")
Next
Con suerte, esto será algo del pasado con la próxima versión de VB. Dado que los iteradores están ganando mucha importancia con los nuevos paradigmas (especialmente LINQ en combinación con la evaluación perezosa), esto tiene una alta prioridad, por lo que sé del blog de Paul Vick. Por otra parte, Paul ya no es el jefe del equipo de VB y aún no he tenido tiempo de ver las conversaciones de PCD.
Aún así, si estás interesado, están vinculados en el blog de Paul .
El Async CTP incluye soporte para Yield
en VB.NET.
Consulte msdn.microsoft.com/en-us/vstudio/gg497937 para obtener información sobre el uso.
¡Y ahora está incluido en la caja con Visual Studio 2012!
El siguiente código da 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;
int result=1;
while (counter < 5)
{
result = result * 2;
counter += 1;
yield return result;
}
}
Está el lindo artículo Use Iterators en VB Now de Bill McCarthy en Visual Studio Magazine sobre cómo emular el yield
en VB.NET. Alternativamente, espere la próxima versión de Visual Basic.
Personalmente, escribo mi propia clase de iterador que hereda de IEnumerator (Of T). Se necesita algún tiempo para hacerlo bien, pero creo que al final es mejor escribirlo y luego tratar de evitarlo. Otro método que he hecho es escribir un método recursivo que devuelve IEnumerable (Of T) y simplemente devuelve List (Of T) y usa .AddRange.
VB.NET tiene la palabra clave Iterator
https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator
Desde Visual Studio 2012 parece