Programmerare, skeptiker, sekulärhumanist, antirasist.
Författare till bok om C64 och senbliven lantis.
Röstar pirat.
2011-09-19
The concept of iterators is well known to C# programmers, but it is new in Visual Basic (available in Visual Studio 11), so this post is probably only interesting for VB programmers. I got some great help from my friend Roger Alsing in explaining what it is that is good about iterators.
An iterator is similar to a function that returns a collection, but an iterator allows the caller to iterate before the collection is populated. The iterator is implemented as a function with the keyword Iterator, but it is actually compiled to an object.
Public Iterator Function Test() As IEnumerable(Of Integer)
This is an iterator named Test that returns integers. The return type declared must be an IEnumerable of the type your iterator contains. This iterator returns Integer values, and therefore the return type is set to an IEnumerable(Of Integer). This is a usage example of our iterator:
For Each I As Integer In Me.Test() MessageBox.Show(I.ToString()) Next
Of course, a bunch of integer values will pop up on screen. But lets check the full implementation of the Test iterator.
Public Iterator Function Test() As IEnumerable(Of Integer) Yield 10 Yield 20 Yield 30 End Function
When the For Each loop is done iterating, three message boxes have popped up. They first displays 10, the second 20 and the third 30. So why not just return an array of {10, 20, 30}?
Like I mentioned, a function that returns a collection must load the collection before returning it. Imagine that you want to return 10 objects, each object takes one second to load. This gives you a pause of 10 seconds before the iteration starts. Example:
Public Function ReturnTenThings() As List(Of String) Dim Ret As New List(Of String)() For I As Integer = 0 To 9 Threading.Thread.Sleep(1000) Ret.Add((I + 1).ToString()) Next Return Ret End Function
This iteration will not start until 10 seconds have passed:
For Each X As String In Me.ReturnTenThings() MessageBox.Show(X) Next
If we rewrite ReturnTenThings to be an iterator, like this…
Public Iterator Function ReturnTenThings() As IEnumerable(Of String) Dim Ret As New List(Of String)() For I As Integer = 0 To 9 Threading.Thread.Sleep(1000) Yield (I + 1).ToString() Next End Function
…the same iteration will still take 10 seconds to complete, but it will start after just one second.
Finally, a word of warning. If you need to know before you start your iteration, how many elements it holds, don’t just read the Count property of your iterator, because that will execute your code. If you need to know, copy the elements to a list, and read the Count property of that list. This code will take 20 seconds to execute, because the iterator runs twice:
MessageBox.Show(Me.ReturnTenThings().Count.ToString()) For Each X As String In Me.ReturnTenThings() MessageBox.Show(X) Next
Categories: Visual Studio 11
Bjud mig på en kopp kaffe (20:-) som tack för bra innehåll!
Leave a Reply