Visual Basic 11 的 Iterator 與 Yield 心得筆記(3)

以下範例會實作一個 Zoo 類別,此類別裡可儲存 Animal 私有類別資料,資料很簡單,就名稱與分類,分類只有簡單兩種,鳥類與哺乳類。讓我們看看在類別裡如何使用 Iterator 與 Yield。

''' <summary>
''' Zoo 類別,可存放哺乳類與鳥類資料
''' </summary>
Class Zoo
    Implements IEnumerable

    ''' <summary>
    ''' 私有 Animal類別,有名稱和分類兩個屬性
    ''' </summary>
    Private Class Animal
        Public Property Name As String
        Public Property Type As TypeEnum

        ' 簡單分類
        Public Enum TypeEnum
            Bird ' 鳥類
            Mammal ' 哺乳類
        End Enum
    End Class

    Private animals As New List(Of Animal)

    ''' <summary>
    ''' 新增哺乳類
    ''' </summary>
    ''' <param name="name">名稱</param>
    Sub AddMammal(ByVal name As String)
        Dim thisAnimal As New Animal() With {.Name = name,
                                            .Type = Animal.TypeEnum.Mammal}
        animals.Add(thisAnimal)
    End Sub

    ''' <summary>
    ''' 新增鳥類
    ''' </summary>
    ''' <param name="name">名稱</param>
    Sub AddBird(ByVal name As String)
        Dim thisAnimal As New Animal() With {.Name = name,
                                            .Type = Animal.TypeEnum.Bird}
        animals.Add(thisAnimal)
    End Sub

    ' 實作 GetEnumerator 方法
    Iterator Function GetEnumerator() As IEnumerator Implements _
                                         IEnumerable.GetEnumerator

        ' 回傳列舉值
        For Each theAnimal As Animal In animals
            Yield theAnimal.Name
        Next
    End Function

    ' 唯讀,回傳哺乳類
    Public ReadOnly Property Mammals As IEnumerable
        Get
            Return AnimalsForType(Animal.TypeEnum.Mammal)
        End Get
    End Property

    ' 唯讀,回傳鳥類
    Public ReadOnly Property Birds As IEnumerable
        Get
            Return AnimalsForType(Animal.TypeEnum.Bird)
        End Get
    End Property

    ' 舉列動物分類
    Private Iterator Function AnimalsForType(type As Animal.TypeEnum) As IEnumerable
        For Each theAnimal As Animal In animals
            ' 找出我們要的分類
            If (theAnimal.Type = type) Then
                Yield theAnimal.Name
            End If
        Next
    End Function
End Class

第一個重點,前面心得已經提過幾次,我們必須實作 IEnumerable.GetEnumerator ,也就是它讓我們有的型別有列舉的能力。第二個重點,AnimalsForType()方法,等一下希望能直接透過動物分類去找出目前此分類中有那些動物,因此我們實作了一個 Iterator Function 來幫忙。

我們看主程式如何呼叫:


Module Module1
    Sub Main()
        Dim theZoo As New Zoo()

        ' 新增動物資料
        theZoo.AddMammal("鯨魚")
        theZoo.AddMammal("犀牛")
        theZoo.AddBird("企鵝")
        theZoo.AddBird("鴕鳥")

        ' 輸出所有動物
        For Each name As String In theZoo
            Console.Write(name & " ")
        Next
        Console.WriteLine()
        Console.ReadLine()

        ' 輸出:鯨魚 犀牛 企鵝 鴕鳥

        ' 輸出鳥類
        For Each name As String In theZoo.Birds
            Console.Write(name & " ")
        Next
        Console.WriteLine()
        Console.ReadLine()

        ' 輸出:企鵝 鴕鳥

        ' 輸出哺乳類
        For Each name As String In theZoo.Mammals
            Console.Write(name & " ")
        Next
        Console.WriteLine()
        Console.ReadLine()

        ' 輸出:鯨魚 犀牛
    End Sub
End Module

第一個 For Each 是 IEnumerable.GetEnumerator 提供功能。第二個與第三個 For Each 是透過唯讀屬性來呼叫 AnimalsForType() 方法,而 AnimalsForType 方法透過 Iterator 與 Yield 的幫忙提供了列舉的能力。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。