# 集合 (Visual Basic)Collections (Visual Basic)

## 使用簡單的集合Using a Simple Collection

' Create a list of strings.
Dim salmons As New List(Of String)

' Iterate through the list.
For Each salmon As String In salmons
Console.Write(salmon & " ")
Next
'Output: chinook coho pink sockeye


' Create a list of strings by using a
' collection initializer.
Dim salmons As New List(Of String) From
{"chinook", "coho", "pink", "sockeye"}

For Each salmon As String In salmons
Console.Write(salmon & " ")
Next
'Output: chinook coho pink sockeye


Dim salmons As New List(Of String) From
{"chinook", "coho", "pink", "sockeye"}

For index = 0 To salmons.Count - 1
Console.Write(salmons(index) & " ")
Next
'Output: chinook coho pink sockeye


' Create a list of strings by using a
' collection initializer.
Dim salmons As New List(Of String) From
{"chinook", "coho", "pink", "sockeye"}

' Remove an element in the list by specifying
' the object.
salmons.Remove("coho")

For Each salmon As String In salmons
Console.Write(salmon & " ")
Next
'Output: chinook pink sockeye


Dim numbers As New List(Of Integer) From
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

' Remove odd numbers.
For index As Integer = numbers.Count - 1 To 0 Step -1
If numbers(index) Mod 2 = 1 Then
' Remove the element by specifying
' the zero-based index in the list.
numbers.RemoveAt(index)
End If
Next

' Iterate through the list.
' A lambda expression is placed in the ForEach method
' of the List(T) object.
numbers.ForEach(
Sub(number) Console.Write(number & " "))
' Output: 0 2 4 6 8


Private Sub IterateThroughList()
Dim theGalaxies As New List(Of Galaxy) From
{
New Galaxy With {.Name = "Tadpole", .MegaLightYears = 400},
New Galaxy With {.Name = "Pinwheel", .MegaLightYears = 25},
New Galaxy With {.Name = "Milky Way", .MegaLightYears = 0},
New Galaxy With {.Name = "Andromeda", .MegaLightYears = 3}
}

For Each theGalaxy In theGalaxies
With theGalaxy
Console.WriteLine(.Name & "  " & .MegaLightYears)
End With
Next

' Output:
'  Pinwheel  25
'  Milky Way  0
'  Andromeda  3
End Sub

Public Class Galaxy
Public Property Name As String
Public Property MegaLightYears As Integer
End Class


## 集合的種類Kinds of Collections

.NET Framework 會提供很多常見的集合。Many common collections are provided by the .NET Framework. 各個類型的集合都是針對特定用途來設計。Each type of collection is designed for a specific purpose.

• System.Collections classes

• Visual Basic Collection 類別Visual Basic Collection class

### System.Collections.Generic 類別System.Collections.Generic Classes

Dictionary<TKey,TValue> 表示根據索引鍵所整理的索引鍵/值組集合。Represents a collection of key/value pairs that are organized based on the key.
List<T> 表示可以依照索引存取的物件清單。Represents a list of objects that can be accessed by index. 提供搜尋、排序和修改清單的方法。Provides methods to search, sort, and modify lists.
Queue<T> 表示物件的先進先出 (FIFO) 集合。Represents a first in, first out (FIFO) collection of objects.
SortedList<TKey,TValue> 代表根據關聯的 IComparer<T> 實作，依索引鍵所排序的索引鍵/值組集合。Represents a collection of key/value pairs that are sorted by key based on the associated IComparer<T> implementation.
Stack<T> 表示物件的後進先出 (LIFO) 集合。Represents a last in, first out (LIFO) collection of objects.

### System.Collections.Concurrent 類別System.Collections.Concurrent Classes

Some classes included in the System.Collections.Concurrent namespace are BlockingCollection<T>, ConcurrentDictionary<TKey,TValue>, ConcurrentQueue<T>, and ConcurrentStack<T>.

### System.Collections 類別System.Collections Classes

System.Collections 命名空間中的類別不會將項目儲存為特別類型物件，而是會儲存為 Object 類型的物件。The classes in the System.Collections namespace do not store elements as specifically typed objects, but as objects of type Object.

ArrayList 代表會視需要動態增加大小的物件陣列。Represents an array of objects whose size is dynamically increased as required.
Hashtable 代表根據索引鍵的雜湊程式碼，所整理的索引鍵/值組集合。Represents a collection of key/value pairs that are organized based on the hash code of the key.
Queue 表示物件的先進先出 (FIFO) 集合。Represents a first in, first out (FIFO) collection of objects.
Stack 表示物件的後進先出 (LIFO) 集合。Represents a last in, first out (LIFO) collection of objects.

System.Collections.Specialized 命名空間會提供特製化類型和強型別集合類別，例如只有字串的集合，以及連結串列和 Hybrid 字典。The System.Collections.Specialized namespace provides specialized and strongly typed collection classes, such as string-only collections and linked-list and hybrid dictionaries.

### Visual Basic Collection 類別Visual Basic Collection Class

Visual Basic Collection 類別會將其所有項目儲存為類型 Object，因此可以加入屬於任何資料類型的項目。The Visual Basic Collection class stores all its elements as type Object, so you can add an item of any data type. 無法確定加入的資料類型皆適當無誤。There is no safeguard against inappropriate data types being added.

## 實作索引鍵/值組集合。Implementing a Collection of Key/Value Pairs

Dictionary<TKey,TValue> 泛型集合可讓您使用每個項目的索引鍵來存取集合中的項目。The Dictionary<TKey,TValue> generic collection enables you to access to elements in a collection by using the key of each element. 加入字典中的每一個項目都是由值及其關聯索引鍵所組成。Each addition to the dictionary consists of a value and its associated key. 使用其索引鍵擷取值的速度非常快，因為 Dictionary 類別是實作為雜湊表。Retrieving a value by using its key is fast because the Dictionary class is implemented as a hash table.

Private Sub IterateThroughDictionary()
Dim elements As Dictionary(Of String, Element) = BuildDictionary()

For Each kvp As KeyValuePair(Of String, Element) In elements
Dim theElement As Element = kvp.Value

Console.WriteLine("key: " & kvp.Key)
With theElement
Console.WriteLine("values: " & .Symbol & " " &
.Name & " " & .AtomicNumber)
End With
Next
End Sub

Private Function BuildDictionary() As Dictionary(Of String, Element)
Dim elements As New Dictionary(Of String, Element)

Return elements
End Function

Private Sub AddToDictionary(ByVal elements As Dictionary(Of String, Element),
ByVal symbol As String, ByVal name As String, ByVal atomicNumber As Integer)
Dim theElement As New Element

theElement.Symbol = symbol
theElement.Name = name
theElement.AtomicNumber = atomicNumber

End Sub

Public Class Element
Public Property Symbol As String
Public Property Name As String
Public Property AtomicNumber As Integer
End Class


Private Function BuildDictionary2() As Dictionary(Of String, Element)
Return New Dictionary(Of String, Element) From
{
{"K", New Element With
{.Symbol = "K", .Name = "Potassium", .AtomicNumber = 19}},
{"Ca", New Element With
{.Symbol = "Ca", .Name = "Calcium", .AtomicNumber = 20}},
{"Sc", New Element With
{.Symbol = "Sc", .Name = "Scandium", .AtomicNumber = 21}},
{"Ti", New Element With
{.Symbol = "Ti", .Name = "Titanium", .AtomicNumber = 22}}
}
End Function


Private Sub FindInDictionary(ByVal symbol As String)
Dim elements As Dictionary(Of String, Element) = BuildDictionary()

If elements.ContainsKey(symbol) = False Then
Else
Dim theElement = elements(symbol)
Console.WriteLine("found: " & theElement.Name)
End If
End Sub


Private Sub FindInDictionary2(ByVal symbol As String)
Dim elements As Dictionary(Of String, Element) = BuildDictionary()

Dim theElement As Element = Nothing
If elements.TryGetValue(symbol, theElement) = False Then
Else
Console.WriteLine("found: " & theElement.Name)
End If
End Sub


## 使用 LINQ 存取集合Using LINQ to Access a Collection

LINQ (Language-Integrated Query (LINQ)) 可用來存取集合。LINQ (Language-Integrated Query) can be used to access collections. LINQ 查詢提供篩選、排序和分組功能。LINQ queries provide filtering, ordering, and grouping capabilities. 如需詳細資訊，請參閱 < Getting Started with Visual Basic 中的 LINQFor more information, see Getting Started with LINQ in Visual Basic.

Private Sub ShowLINQ()
Dim elements As List(Of Element) = BuildList()

' LINQ Query.
Dim subset = From theElement In elements
Where theElement.AtomicNumber < 22
Order By theElement.Name

For Each theElement In subset
Console.WriteLine(theElement.Name & " " & theElement.AtomicNumber)
Next

' Output:
'  Calcium 20
'  Potassium 19
'  Scandium 21
End Sub

Private Function BuildList() As List(Of Element)
Return New List(Of Element) From
{
{New Element With
{.Symbol = "K", .Name = "Potassium", .AtomicNumber = 19}},
{New Element With
{.Symbol = "Ca", .Name = "Calcium", .AtomicNumber = 20}},
{New Element With
{.Symbol = "Sc", .Name = "Scandium", .AtomicNumber = 21}},
{New Element With
{.Symbol = "Ti", .Name = "Titanium", .AtomicNumber = 22}}
}
End Function

Public Class Element
Public Property Symbol As String
Public Property Name As String
Public Property AtomicNumber As Integer
End Class


## 為集合排序Sorting a Collection

ListCars 方法中，cars.Sort() 陳述式會排序清單。In the ListCars method, the cars.Sort() statement sorts the list. List<T>Sort 方法的這個呼叫，會導致 CompareTo 方法對 ListCar 物件自動呼叫。This call to the Sort method of the List<T> causes the CompareTo method to be called automatically for the Car objects in the List.

Public Sub ListCars()

' Create some new cars.
Dim cars As New List(Of Car) From
{
New Car With {.Name = "car1", .Color = "blue", .Speed = 20},
New Car With {.Name = "car2", .Color = "red", .Speed = 50},
New Car With {.Name = "car3", .Color = "green", .Speed = 10},
New Car With {.Name = "car4", .Color = "blue", .Speed = 50},
New Car With {.Name = "car5", .Color = "blue", .Speed = 30},
New Car With {.Name = "car6", .Color = "red", .Speed = 60},
New Car With {.Name = "car7", .Color = "green", .Speed = 50}
}

' Sort the cars by color alphabetically, and then by speed
' in descending order.
cars.Sort()

' View all of the cars.
For Each thisCar As Car In cars
Console.Write(thisCar.Speed.ToString & " ")
Console.Write(thisCar.Name)
Console.WriteLine()
Next

' Output:
'  blue  50 car4
'  blue  30 car5
'  blue  20 car1
'  green 50 car7
'  green 10 car3
'  red   60 car6
'  red   50 car2
End Sub

Public Class Car
Implements IComparable(Of Car)

Public Property Name As String
Public Property Speed As Integer
Public Property Color As String

Public Function CompareTo(ByVal other As Car) As Integer _
Implements System.IComparable(Of Car).CompareTo
' A call to this method makes a single comparison that is
' used for sorting.

' Determine the relative order of the objects being compared.
' Sort by color alphabetically, and then by speed in
' descending order.

' Compare the colors.
Dim compare As Integer
compare = String.Compare(Me.Color, other.Color, True)

' If the colors are the same, compare the speeds.
If compare = 0 Then
compare = Me.Speed.CompareTo(other.Speed)

' Use descending order for speed.
compare = -compare
End If

Return compare
End Function
End Class


## 定義自訂集合Defining a Custom Collection

GetEnumerator 方法會傳回 ColorEnumerator 類別的執行個體。The GetEnumerator method returns an instance of the ColorEnumerator class. ColorEnumerator 實作 IEnumerator 介面，而此介面會要求實作 Current 屬性、MoveNext 方法和 Reset 方法。ColorEnumerator implements the IEnumerator interface, which requires that the Current property, MoveNext method, and Reset method be implemented.

Public Sub ListColors()
Dim colors As New AllColors()

For Each theColor As Color In colors
Console.Write(theColor.Name & " ")
Next
Console.WriteLine()
' Output: red blue green
End Sub

' Collection class.
Public Class AllColors
Implements System.Collections.IEnumerable

Private _colors() As Color =
{
New Color With {.Name = "red"},
New Color With {.Name = "blue"},
New Color With {.Name = "green"}
}

Public Function GetEnumerator() As System.Collections.IEnumerator _
Implements System.Collections.IEnumerable.GetEnumerator

Return New ColorEnumerator(_colors)

' Instead of creating a custom enumerator, you could
' use the GetEnumerator of the array.
'Return _colors.GetEnumerator
End Function

' Custom enumerator.
Private Class ColorEnumerator
Implements System.Collections.IEnumerator

Private _colors() As Color
Private _position As Integer = -1

Public Sub New(ByVal colors() As Color)
_colors = colors
End Sub

Public ReadOnly Property Current() As Object _
Implements System.Collections.IEnumerator.Current
Get
Return _colors(_position)
End Get
End Property

Public Function MoveNext() As Boolean _
Implements System.Collections.IEnumerator.MoveNext
_position += 1
Return (_position < _colors.Length)
End Function

Public Sub Reset() Implements System.Collections.IEnumerator.Reset
_position = -1
End Sub
End Class
End Class

' Element class.
Public Class Color
Public Property Name As String
End Class


## 迭代器Iterators

「迭代器」是用來在集合上執行自訂反覆項目。An iterator is used to perform a custom iteration over a collection. 迭代器可以是方法或 get 存取子。An iterator can be a method or a get accessor. 迭代器會使用產生陳述式來傳回一次一個集合的每個項目。An iterator uses a Yield statement to return each element of the collection one at a time.

Public Sub ListEvenNumbers()
For Each number As Integer In EvenSequence(5, 18)
Console.Write(number & " ")
Next
Console.WriteLine()
' Output: 6 8 10 12 14 16 18
End Sub

Private Iterator Function EvenSequence(
ByVal firstNumber As Integer, ByVal lastNumber As Integer) _
As IEnumerable(Of Integer)

' Yield even numbers in the range.
For number = firstNumber To lastNumber
If number Mod 2 = 0 Then
Yield number
End If
Next
End Function