說來簡單,您只需實作整個 IEnumerable 介面或 IEnumerable(Of T) 介面。我們以MSDN中 IEnumerable 介面 範例來說明 IEnumerable 介面實作。
Imports System
Imports System.Collections
''' <summary>
''' Person 類例
''' </summary>
Public Class Person
Public firstName As String
Public lastName As String
''' <summary>
''' 建構式
''' </summary>
''' <param name="fName">姓</param>
''' <param name="lName">名子</param>
Sub New(ByVal fName As String, ByVal lName As String)
Me.firstName = fName
Me.lastName = lName
End Sub
End Class
首先,宣告一個Class Person(個人),裡面只有兩個屬性,firstName 和 lastName,並且了一個簡單的初始化建構式。
''' <summary>
''' People 類別
''' </summary>
''' <remarks>實作 IEnumerable</remarks>
Public Class People
Implements IEnumerable
' 私有 _person()陣列變數,存放 Person類別資料
Private _people() As Person
''' <summary>
''' 建構式
''' </summary>
''' <param name="pArray">Person 陣列</param>
Sub New(pArray() As Person)
' 初始化陣列物件
_people = New Person(pArray.Length - 1) {}
' 儲存至私有 _person()陣列變數
Dim i As Integer
For i = 0 To pArray.Length - 1
' 將傳入物件陣列儲存在 _people陣列
_people(i) = pArray(i)
Next i
End Sub
''' <summary>
''' 實作 IEnumerable.GetEnumerator 方法
''' </summary>
''' <returns>列舉 _people()陣列的結果</returns>
Function GetEnumerator() As IEnumerator _
Implements IEnumerable.GetEnumerator
' 回傳列舉 _people陣列結果
Return New PeopleEnum(_people)
End Function
End Class
宣告一個Class People(人),重點在第二行,它實作了 IEnumerable介面,當您輸入完 Implements IEnumerable 按下 Enter 後,會自動跳出需實作的函式,即 GetEnumerator() 函式。People類別主要是要存放 Person(個人)類別資料,存放於陣列之中,然實透過實作 GetEnumerator() 函式,讓 People類別擁有可反覆運作的能力。在 GetEnumerator() 函式中,我們還需要透過一個 PeopleEnum類別來幫忙完成最後一件事。
''' <summary>
''' 列舉 People 類別
''' </summary>
''' <remarks>實作 IEnumerable</remarks>
Class PeopleEnum
Implements IEnumerator
Public _people() As Person
' 在第一個列舉之前的位置
' 直到第一次呼叫 MoveNext()
Dim position As Integer = -1
''' <summary>
''' 建構式,初始化 _people() 陣列
''' </summary>
''' <param name="list">Person陣列</param>
Sub New(list() As Person)
_people = list
End Sub
''' <summary>
''' 實作 MoveNext() 函式
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Function MoveNext() As Boolean _
Implements IEnumerator.MoveNext
position = position + 1
Return (position < _people.Length)
End Function
''' <summary>
''' 實作 Reset() 副程式
''' </summary>
Sub Reset() Implements IEnumerator.Reset
position = -1
End Sub
''' <summary>
''' 實作唯讀 Current() 屬性
''' </summary>
''' <value></value>
''' <returns>_people陣列值</returns>
''' <remarks></remarks>
Public ReadOnly Property Current() As Object _
Implements IEnumerator.Current
Get
Try
' 回傳現在位置的 _people陣列值
Return _people(position)
Catch ex As IndexOutOfRangeException
Throw New InvalidOperationException()
End Try
End Get
End Property
End Class
PeopleEnum類別,很明顯是在進行列舉用的類別。
注意實作的是 IEnumerator介面,我們必須實作此 IEnumerator介面裡的三個方法。首先是 position 變數,For Each 每次呼叫時的動作,其實都是呼叫 MoveNext() 函式,陣列由 0 開始,所以第一次呼叫的值應該是如 _people(0) 來回傳第一筆陣列值,所以我們一開始先讓 position 的值為 -1。在 MoveNext() 函式中,我們做的事很簡單,一是先進行 +1 的動作,然後判斷 +1 之後是否超出陣列大小。在 Reset() 更簡單,Reset 代表重新設定,就讓 position 回到最原頭的 -1。最後一個也是最重要的屬性,Current() 屬性,也就是回傳當前陣列的值。
最後整個完成的類別圖:
![]() |
| 圖一:實作 IEnumerable 介面範例類別圖 |
最後執行的程式碼。
Module Module1
Sub Main()
Dim peopleArray() As Person = {
New Person("John", "Smith"),
New Person("Jim", "Johnson"),
New Person("Sue", "Rabon")}
Dim peopleList As New People(peopleArray)
Dim p As Person
' 注意,peopleList 可以使用 For Each 列舉
For Each p In peopleList
Console.WriteLine(p.firstName + " " + p.lastName)
Next
Console.ReadLine()
' 結果:
'
' John Smith
' Jim Johnson
' Sue Rabon
End Sub
End Module
我們傳入一個 Person的陣列物件(peopleArray)給 People類別的執行個體 peopleList。 peopleList 執行個體為什麼能有列舉能力,因為 People類別有實作 IEnumerable介面。那您會說,我平常在用的 Array、ArrayList、List … 不都可以直接使用嗎?對,你去查查 MSDN,那是因為人家在這些類別裡已經幫您實作好 IEnumerable介面。我們在來看一個簡單的範例,一週的日期。
Module Module1
Sub Main()
' 參考 ArrayList 的宣告
' Public Class ArrayList
' Implements IList, ICollection, IEnumerable, ICloneable
Dim weekDayList As New ArrayList From
{"Sun-星期日", "Mon-星期一", "Tue-星期二",
"Wed-星期三", "Thu-星期四", "Fri-星期五", "Sat-星期六"}
' 找出 S 開頭的日期
Console.WriteLine("使用 For Each 找出 S 開頭的日期")
Dim day As String = ""
For Each day In weekDayList
If day.StartsWith("S") Then
Console.WriteLine(day.ToString())
End If
Next
Console.WriteLine()
Console.ReadLine()
Console.WriteLine("使用 IEnumerable介面來找出 T 開題的日期")
' 讓 dayEnum 擁有列舉能力
Dim dayEnum As IEnumerator = weekDayList.GetEnumerator()
While dayEnum.MoveNext
Dim dayString As String = dayEnum.Current.ToString()
If dayString.StartsWith("T") Then
Console.WriteLine(dayString)
End If
End While
Console.WriteLine()
Console.ReadLine()
' 結果
' 使用 For Each 找出 S 開頭的日期
' Sun-星期日
' Sat-星期六
'
' 使用 IEnumerable介面來找出 T 開題的日期
' Tue-星期二
' Thu-星期四
End Sub
End Module
ArrayList類別是一個已經實作 IEnumerable介面的類別,所以我們很輕易在程式中使用 For Each 來取得資料。第二段程式主要是透過 GetEnumerator() 來讓 dayEnum 有列舉能力(IEnumerator介面提供),然後透過 MoveNext 與 Current 來移動陣列與取出陣列值。
看完第一段(Person)與第二段(dayEnum)程式碼,有沒有發現,人家幫我們做了好多事。但如一開頭所言,一句「實作 IEnumerable介面」,你看看要做多少事?

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