Try ~ Catch與 Iterator ~ Yield
程式裡不可能沒有 Try ~ Catch,我們看看 Iterator 與 Yield 在 Try ~ Catch 裡的使用。
Module Module1
''' <summary>
''' 測試 Iterator 與 Yield 與 Try ~ Catch
''' </summary>
Private Iterator Function TestTryCatch() As IEnumerable(Of Integer)
Try
Yield 3
Yield 4
Throw New Exception("出事了!")
Yield 5
Yield 6
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
Console.WriteLine("Finally 已被執行!")
End Try
End Function
Sub Main()
For Each number As Integer In TestTryCatch()
Console.WriteLine(number)
Next
Console.ReadLine()
' 輸出:
' 3
' 4
' 出事了!
' Finally 已被執行!
End Sub
End Module
你可以發現,執行至 Throw New Exception() 之後,因為進入的 Catch 然後執行至 Finally,程式就結束。也就是說,當程式執行至一半擲出例外(Catch),整個 Iterator Function 就會停止不在進行。而 Finally 是不管有沒有發生例外,都還是會被執行。這很符合我們的常理。
匿名方法(Anonymous Methods)與 Iterator ~ Yield
Module Module1
Sub Main()
Dim iterateSequence = Iterator Function() As IEnumerable(Of Integer)
Yield 1
Yield 2
Yield 3
End Function
' 呼叫匿名方法
For Each number As Integer In iterateSequence()
Console.Write(number & " ")
Next
Console.ReadLine()
' 輸出: 1 2 3
End Sub
End Module
與之前差異不大,透過 Iterator 與 Yield 的幫忙,讓匿名方法可以擁有舉列的能力。我們再舉一個範例:
Module Module1
''' <summary>
''' 取得數字的順序
''' </summary>
''' <param name="low">最小不得小於1</param>
''' <param name="high">最大不得大於100</param>
''' <returns>有順序數字</returns>
Function GetSequence(low As Integer,
high As Integer) As IEnumerable
' 驗證參數
If low <= 1 Then
Throw New ArgumentException("low is too low")
End If
If high >= 100 Then
Throw New ArgumentException("high is too high")
End If
' 透過可舉列的匿名方法建立順序
Dim iterateSequence = Iterator Function() As IEnumerable
For index = low To high
Yield index
Next
End Function
Return iterateSequence()
End Function
Sub Main()
For Each number As Integer In GetSequence(38, 43)
Console.Write(number & " ")
Next
Console.ReadLine()
' 輸出: 38 39 40 41 42 43
End Sub
End Module
這裡注意驗證參數的部份,如果你把驗證參數寫在匿名方法裡,那必須等到 For Each 第一次去呼叫 Iterator 時,才會開始發生作用。在 Iterator 的說明文件中有一段話:「
Iterators 是LINQ查詢中延後執行行為的基礎。」又學到一招。【註】在 MSDN 說明中「在 C# 裡 yield 陳述式不能出現於匿名方法中。」
泛型集合(Generic List)與 Iterator ~ Yield
下面這個範例,是 Stack(Of T)泛型類別實作 IEnumerable(Of T)泛型介面。