Rendimento em VB.NET

C # tem a palavra-chave chamada yield . VB.NET não possui essa palavra-chave. Como os programadores do Visual Basic contornaram a falta dessa palavra-chave? Eles implementam sua própria class de iteradores? Ou eles tentam e codificam para evitar a necessidade de um iterador?

A palavra-chave yield força o compilador a fazer alguma codificação nos bastidores. A implementação de iteradores em C # e suas conseqüências (parte 1) tem um bom exemplo disso.

Nota: Esta resposta é antiga agora. Blocos iteradores foram adicionados ao VB.NET desde então

C # traduz a palavra-chave yield em uma máquina de estado em tempo de compilation. VB.NET não tem a palavra-chave yield, mas tem seu próprio mecanismo para incorporar com segurança o estado dentro de uma function que não está facilmente disponível em C #.

A palavra-chave static C # é normalmente traduzida para o Visual Basic usando a palavra-chave Shared , mas há dois lugares em que as coisas ficam confusas. Uma é que uma class estática C # é realmente um módulo no Visual Basic em vez de uma class Shared (você acha que eles permitem que você codifique de qualquer forma no Visual Basic, mas noooo). A outra é que o VB.NET tem sua própria palavra-chave Static . No entanto, o Static tem um significado diferente no VB.NET.

Você usa a palavra-chave Static no VB.NET para declarar uma variável dentro de uma function e, quando você faz, a variável mantém seu estado entre as chamadas de function. Isso é diferente de declarar um membro de class estática privada em C #, porque é garantido que um membro de function estática em VB.NET também seja thread-safe, em que o compilador o traduz para usar a class Monitor em tempo de compilation.

Então, por que escrever tudo isso aqui? Bem, deve ser possível construir uma class Iterator genérico reutilizável Iterator (ou Iterator(Of T) em VB.NET). Nesta class, você implementaria a máquina de estado usada por C #, com os methods Yield() e Break() que correspondem às palavras-chave C #. Então você poderia usar uma instância estática (no sentido VB.NET) em uma function para que ela possa fazer basicamente o mesmo trabalho que o yield C # em aproximadamente a mesma quantidade de código (descartando a própria implementação da class, já que seria infinitamente reutilizável).

Eu não me importei o suficiente com o Yield para tentar por mim mesmo, mas deveria ser factível. Dito isto, também está longe de ser trivial, como Eric Lippert, membro da equipe de c #, chama isso de ” a transformação mais complicada do compilador “.

Eu também passei a acreditar desde que escrevi o primeiro rascunho disso há mais de um ano que realmente não é possível de forma significativa até que o Visual Studio 2010 seja lançado, já que seria necessário enviar vários lambdas para a class Iterator e, assim, ser realmente prático, precisamos do suporte do .NET 4 para lambdas de várias linhas.

O CTP Async inclui suporte para Yield em VB.NET.

Consulte Iteradores no Visual Basic para obter informações sobre o uso.

E agora está incluído na checkbox com o Visual Studio 2012!

Há o belo artigo Use Iterators in VB Now de Bill McCarthy no Visual Studio Magazine sobre a emulação de yield em VB.NET. Alternativamente, aguarde a próxima versão do Visual Basic.

Eu, pessoalmente, apenas escrevo minha própria class iterator que herda do IEnumerator (Of T). Demora algum tempo para acertar, mas acho que no final é melhor escrevê-lo para a direita, em seguida, tentar evitá-lo. Outro método que tenho feito é escrever um método recursivo que retorna IEnumerable (Of T) e apenas retorna List (Of T) e usa .AddRange.

Felizmente agora temos retorno de Yield
Aqui está um exemplo do meu projeto + implementando uma interface com a function 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 

É assim que eu extraio todas as propriedades do lado de fora:

 For Each itm As SLA.IStatus In outputlist For Each it As Object In itm.GetEnumerator() Debug.Write(it & " ") Next Debug.WriteLine("") Next 

Espero que isso seja uma coisa do passado com a próxima versão do VB. Como os iteradores estão realmente ganhando muita importância com novos paradigmas (especialmente o LINQ em combinação com a avaliação lenta), isso tem uma alta prioridade, até onde eu sei no blog de Paul Vick. Então, novamente, Paul não é mais o chefe da equipe do VB e eu ainda não tive tempo de assistir às palestras do PCD.

Ainda assim, se você estiver interessado, eles estão vinculados ao blog de Paul .

O código abaixo dá a saída

2, 4, 8, 16, 32

Em 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 

Em c #

 private void Form1_Load(object sender, EventArgs e) { foreach (int i in setofNumbers()) { MessageBox.Show(i.ToString()); } } public static IEnumerable setofNumbers() { int counter=0; int result=1; while (counter < 5) { result = result * 2; counter += 1; yield return result; } } 

VB.NET tem a palavra-chave Iterator https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator

Desde Visual Studio 2012 parece