Rendimento in VB.NET

C # ha la parola chiave chiamata resa . VB.NET manca questa parola chiave. In che modo i programmatori di Visual Basic hanno risolto la mancanza di questa parola chiave? Implementano la propria class iteratore? Oppure provano e codificano per evitare la necessità di un iteratore?

La parola chiave yield costringe il compilatore a fare un po ‘di codice dietro le quinte. L’implementazione degli iteratori in C # e le sue conseguenze (parte 1) ne sono un buon esempio.

Nota: questa risposta è vecchia ora. Da allora i blocchi iteratori sono stati aggiunti a VB.NET

C # traduce la parola chiave yield in una macchina a stati in fase di compilazione. VB.NET non ha la parola chiave yield, ma ha il proprio meccanismo per l’incorporamento sicuro dello stato all’interno di una funzione che non è facilmente disponibile in C #.

La parola chiave static C # viene normalmente tradotta in Visual Basic utilizzando la parola chiave Shared , ma ci sono due punti in cui le cose si confondono. Uno è che una class statica C # è in realtà un modulo in Visual Basic piuttosto che una class condivisa (si potrebbe pensare che ti permettono di codificarlo in entrambi i modi in Visual Basic, ma noooo). L’altro è che VB.NET ha una propria parola chiave Static . Tuttavia, Static ha un significato diverso in VB.NET.

Si utilizza la parola chiave Static in VB.NET per dichiarare una variabile all’interno di una funzione e quando si fa la variabile mantiene il suo stato tra le chiamate di funzione. Questo è diverso rispetto alla semplice dichiarazione di un membro di class statico privato in C #, poiché un membro di funzione statica in VB.NET è garantito anche per essere thread-safe, in quanto il compilatore lo traduce per utilizzare la class Monitor in fase di compilazione.

Allora perché scrivere tutto questo qui? Bene, dovrebbe essere ansible build una class Iterator generica riutilizzabile (o Iterator(Of T) in VB.NET). In questa class implementeresti la macchina a stati usata da C #, con i metodi Yield() e Break() che corrispondono alle parole chiave C #. Quindi è ansible utilizzare un’istanza statica (nel senso VB.NET) in una funzione in modo che alla fine possa fare praticamente lo stesso lavoro del yield C # in circa la stessa quantità di codice (scartando l’implementazione della class stessa, poiché sarebbe infinitamente riutilizzabile).

Non mi è mai importato abbastanza di Yield per tentare da solo, ma dovrebbe essere fattibile. Detto questo, è anche tutt’altro che banale, poiché Eric Lippert, membro del team C #, definisce ” la trasformazione più complicata del compilatore “.

Sono anche venuto a credere da quando ho scritto la prima bozza di questo oltre un anno fa che non è davvero ansible in modo significativo fino a quando non uscirà Visual Studio 2010, in quanto richiederebbe l’invio di più lambda alla class Iterator e quindi essere veramente abbiamo bisogno del supporto di .NET 4 per i lambda multi-line.

Async CTP include il supporto per il Yield in VB.NET.

Vedere Iterators in Visual Basic per informazioni sull’utilizzo.

E ora è incluso nella confezione di Visual Studio 2012!

C’è il bell’articolo Usa Iterators in VB Now di Bill McCarthy in Visual Studio Magazine sull’emulazione del yield in VB.NET. In alternativa, attendere la versione successiva di Visual Basic.

Personalmente scrivo solo la mia propria class iteratore che eredita da IEnumerator (Of T). Ci vuole un po ‘per farlo bene, ma penso che alla fine è meglio scriverlo bene, quindi cercare di evitarlo. Un altro metodo che ho fatto è scrivere un metodo ricorsivo che restituisce IEnumerable (Of T) e restituisce solo List (Of T) e utilizza .AddRange.

Fortunatamente ora abbiamo il Yield rendimento
ecco un esempio del mio progetto + che implementa un’interfaccia con la funzione 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 

Ecco come estraggo tutte le proprietà dall’esterno:

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

Speriamo che questa sarà una cosa del passato con la prossima versione di VB. Dal momento che gli iteratori stanno acquisendo molta importanza con nuovi paradigmi (in particolare LINQ in combinazione con una valutazione lenta), questo ha una priorità molto alta, per quanto ne so dal blog di Paul Vick. Poi di nuovo, Paul non è più il capo della squadra VB e non ho ancora avuto il tempo di guardare i discorsi del PCD.

Tuttavia, se sei interessato, sono collegati nel blog di Paul .

Il codice sottostante fornisce l’output

2, 4, 8, 16, 32

In 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 

In 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 ha la parola chiave Iterator https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/modifiers/iterator

Dal momento che Visual Studio 2012 sembra