Kolekce (Visual Basic)
U mnoha aplikací chcete vytvořit a spravovat skupiny souvisejících objektů. Existují dva způsoby, jak seskupit objekty: vytvořením polí objektů a vytvořením kolekcí objektů.
Pole jsou užitečná pro vytváření a práci s pevným počtem silně typových objektů. Informace o polích naleznete v tématu Arrays.
Kolekce poskytují pružnější způsob práce se skupinami objektů. Na rozdíl od polí mohou skupiny objektů, se kterými pracujete, dynamicky zvětšovat a zmenšovat podle potřeb změny aplikace. U některých kolekcí můžete přiřadit klíč k libovolnému objektu, který vložíte do kolekce, abyste mohli rychle načíst objekt pomocí klíče.
Kolekce je třída, takže před přidáním prvků do této kolekce je nutné deklarovat instanci třídy.
Pokud kolekce obsahuje prvky pouze jednoho typu dat, můžete použít jednu ze tříd v System.Collections.Generic oboru názvů. Obecná kolekce vynutila bezpečnost typů, takže do ní nelze přidat žádný jiný datový typ. Při načítání prvku z obecné kolekce není nutné určit jeho datový typ nebo ho převést.
Poznámka
Příklady v tomto tématu zahrnují příkazy Imports pro System.Collections.Generic System.Linq obory názvů a.
Používání jednoduché kolekce
Příklady v této části používají obecnou List<T> třídu, která umožňuje pracovat se seznamem objektů se silným typem.
Následující příklad vytvoří seznam řetězců a pak projde řetězcem pomocí pro každý z nich... Další příkaz.
' Create a list of strings.
Dim salmons As New List(Of String)
salmons.Add("chinook")
salmons.Add("coho")
salmons.Add("pink")
salmons.Add("sockeye")
' Iterate through the list.
For Each salmon As String In salmons
Console.Write(salmon & " ")
Next
'Output: chinook coho pink sockeye
Pokud je obsah kolekce znám předem, můžete kolekci inicializovat pomocí inicializátoru kolekce . Další informace najdete v tématu inicializátory kolekce.
Následující příklad je stejný jako předchozí příklad, s výjimkou, že inicializátor kolekce se používá pro přidání prvků do kolekce.
' 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
Můžete použít pro... Další příkaz místo For Each příkazu pro iteraci v kolekci. Toho dosáhnete přístupem k prvkům kolekce na pozici indexu. Index prvků začíná na 0 a končí v počtu elementů minus 1.
Následující příklad provede iteraci prvků kolekce pomocí For…Next místo For Each .
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
Následující příklad odebere prvek z kolekce zadáním objektu, který chcete odebrat.
' 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
Následující příklad odstraní prvky z obecného seznamu. Místo For Each příkazu, pro... Použije se další příkaz, který provede iterace v sestupném pořadí. Důvodem je, že RemoveAt metoda způsobí, že prvky po odebraném prvku mají nižší hodnotu indexu.
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
Pro typ prvků v List<T> , můžete také definovat vlastní třídu. V následujícím příkladu Galaxy třída, která je použita v, List<T> je definována v kódu.
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:
' Tadpole 400
' Pinwheel 25
' Milky Way 0
' Andromeda 3
End Sub
Public Class Galaxy
Public Property Name As String
Public Property MegaLightYears As Integer
End Class
Typy kolekcí
K dispozici je mnoho běžných kolekcí .NET Framework. Každý typ kolekce je navržený pro konkrétní účel.
Některé společné třídy kolekcí jsou popsány v této části:
System.Collections.Generic – třídy
System.Collections.Concurrent – třídy
System.Collections – třídy
Visual Basic
CollectionDeník
Třídy System.Collections.Generic
Můžete vytvořit obecnou kolekci pomocí jedné ze tříd v System.Collections.Generic oboru názvů. Obecná kolekce je užitečná, pokud má každá položka v kolekci stejný datový typ. Obecná kolekce vynutila silné typování tím, že umožňuje přidat pouze požadovaný datový typ.
V následující tabulce jsou uvedeny některé z často používaných tříd System.Collections.Generic oboru názvů:
| Třída | Popis |
|---|---|
| Dictionary<TKey,TValue> | Představuje kolekci párů klíč/hodnota, které jsou uspořádány na základě klíče. |
| List<T> | Představuje seznam objektů, které mohou být k dispozici v indexu. Poskytuje metody pro hledání, řazení a úpravy seznamů. |
| Queue<T> | Představuje kolekci objektů first in, First out (FIFO). |
| SortedList<TKey,TValue> | Představuje kolekci párů klíč/hodnota, které jsou seřazeny podle klíče na základě přidružené IComparer<T> implementace. |
| Stack<T> | Představuje kolekci objektů Last in, First out (LIFO). |
Další informace naleznete v tématu běžně používané typy kolekcí, Výběr třídy kolekcea System.Collections.Generic .
Třídy System.Collections.Concurrent
v .NET Framework 4 nebo novějších kolekce v System.Collections.Concurrent oboru názvů poskytují efektivní operace bezpečné pro přístup z více vláken pro přístup k položkám kolekce z více vláken.
Třídy v System.Collections.Concurrent oboru názvů by měly být použity namísto odpovídajících typů v System.Collections.Generic System.Collections oborech názvů a pokaždé, když více vláken přistupuje souběžně k kolekci. další informace naleznete v tématu kolekce vláken-Sejf a System.Collections.Concurrent .
Některé třídy System.Collections.Concurrent , které jsou součástí oboru názvů BlockingCollection<T> , jsou, ConcurrentDictionary<TKey,TValue> , ConcurrentQueue<T> a ConcurrentStack<T> .
Třídy System. Collections
Třídy v System.Collections oboru názvů neukládají prvky jako specificky typové objekty, ale jako objekty typu Object .
Kdykoli je to možné, použijte obecné kolekce v System.Collections.Generic oboru názvů nebo System.Collections.Concurrent obor názvů namísto starších typů v System.Collections oboru názvů.
Následující tabulka uvádí některé často používané třídy v System.Collections oboru názvů:
| Třída | Popis |
|---|---|
| ArrayList | Představuje pole objektů, jejichž velikost se dynamicky zvětšuje podle potřeby. |
| Hashtable | Představuje kolekci párů klíč/hodnota, které jsou uspořádány na základě kódu hash klíče. |
| Queue | Představuje kolekci objektů first in, First out (FIFO). |
| Stack | Představuje kolekci objektů Last in, First out (LIFO). |
System.Collections.SpecializedObor názvů poskytuje specializované třídy kolekcí se silnými typy, jako jsou jenom řetězcové kolekce a propojené seznamy a hybridní slovníky.
Třída Collection v jazyce Visual Basic
třídu Visual Basic lze použít Collection pro přístup k položce kolekce pomocí číselného indexu nebo String klíče. Můžete přidat položky do objektu kolekce buď s nebo bez zadání klíče. Pokud přidáte položku bez klíče, je nutné k ní přistupovat pomocí jejího číselného indexu.
třída Visual Basic Collection ukládá všechny své prvky jako typ Object , takže můžete přidat položku libovolného datového typu. Neexistují žádné záruky proti přidávání nevhodných datových typů.
když použijete třídu Visual Basic Collection , první položka v kolekci má index 1. to se liší od tříd kolekce .NET Framework, pro které je počáteční index 0.
kdykoli je to možné, použijte obecné kolekce v System.Collections.Generic oboru názvů nebo v System.Collections.Concurrent oboru názvů namísto Collection třídy Visual Basic.
Další informace naleznete v tématu Collection.
Implementace kolekce párů klíč/hodnota
Dictionary<TKey,TValue>Obecná kolekce umožňuje přístup k prvkům v kolekci pomocí klíče každého prvku. Každé přidání do slovníku se skládá z hodnoty a jejího přidruženého klíče. Načítání hodnoty pomocí klíče je rychlé, protože Dictionary Třída je implementována jako zatřiďovací tabulka.
Následující příklad vytvoří Dictionary kolekci a iteruje prostřednictvím slovníku pomocí For Each příkazu.
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)
AddToDictionary(elements, "K", "Potassium", 19)
AddToDictionary(elements, "Ca", "Calcium", 20)
AddToDictionary(elements, "Sc", "Scandium", 21)
AddToDictionary(elements, "Ti", "Titanium", 22)
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
elements.Add(Key:=theElement.Symbol, value:=theElement)
End Sub
Public Class Element
Public Property Symbol As String
Public Property Name As String
Public Property AtomicNumber As Integer
End Class
Chcete-li místo toho použít inicializátor kolekce k sestavení Dictionary kolekce, můžete nahradit BuildDictionary metody a AddToDictionary následující metodou.
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
Následující příklad používá ContainsKey metodu a Item[] vlastnost Dictionary pro rychlé vyhledání položky podle klíče. ItemVlastnost umožňuje přístup k položce v elements kolekci pomocí elements(symbol) kódu v Visual Basic.
Private Sub FindInDictionary(ByVal symbol As String)
Dim elements As Dictionary(Of String, Element) = BuildDictionary()
If elements.ContainsKey(symbol) = False Then
Console.WriteLine(symbol & " not found")
Else
Dim theElement = elements(symbol)
Console.WriteLine("found: " & theElement.Name)
End If
End Sub
Následující příklad místo toho používá TryGetValue metodu pro rychlé vyhledání položky podle klíče.
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
Console.WriteLine(symbol & " not found")
Else
Console.WriteLine("found: " & theElement.Name)
End If
End Sub
Přístup ke kolekci pomocí jazyka LINQ
LINQ (jazykově integrovaný dotaz) lze použít pro přístup ke kolekcím. Dotazy LINQ poskytují možnosti filtrování, řazení a seskupování. Další informace najdete v tématu Začínáme s LINQ v Visual Basic.
Následující příklad spustí dotaz LINQ na obecné List . Dotaz LINQ vrátí jinou kolekci, která obsahuje výsledky.
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
Řazení kolekce
Následující příklad znázorňuje postup pro řazení kolekce. Příklad řadí instance Car třídy, které jsou uloženy v List<T> . CarTřída implementuje IComparable<T> rozhraní, které vyžaduje CompareTo implementaci metody.
Každé volání CompareTo metody provede jedno porovnání, které se používá k řazení. Uživatelsky psaný kód v CompareTo metodě vrátí hodnotu pro každé porovnání aktuálního objektu s jiným objektem. Vrácená hodnota je menší než nula, pokud je aktuální objekt menší než druhý objekt, větší než nula, pokud je aktuální objekt větší než druhý objekt a nula, pokud jsou stejné. To umožňuje definovat v kódu kritéria pro větší než, menší než a rovno.
V ListCars metodě cars.Sort() příkaz seřadí seznam. Toto volání Sort metody metody List<T> způsobí, že CompareTo Metoda bude automaticky volána pro Car objekty v 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.Color.PadRight(5) & " ")
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
Definice vlastní kolekce
Kolekci můžete definovat implementací IEnumerable<T> IEnumerable rozhraní nebo. Další informace najdete v tématu výčet kolekce.
i když můžete definovat vlastní kolekci, je obvykle vhodnější použít kolekce, které jsou součástí .NET Framework, které jsou popsány v části druhy kolekcí výše v tomto tématu.
Následující příklad definuje vlastní třídu kolekce s názvem AllColors . Tato třída implementuje IEnumerable rozhraní, které vyžaduje GetEnumerator implementaci metody.
GetEnumeratorMetoda vrátí instanci ColorEnumerator třídy. ColorEnumerator implementuje IEnumerator rozhraní, které vyžaduje, aby byla Current MoveNext implementována vlastnost, metoda a Reset metoda.
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
Iterátory
Iterátor se používá k provedení vlastní iterace v kolekci. Iterátor může být metoda nebo get přistupující objekt. Iterátor používá příkaz yield k vrácení každého prvku kolekce v jednom okamžiku.
Zavoláte iterátor pomocí a pro každou z nich... Další příkaz. Každá iterace For Each smyčky volá iterátor. Při Yield dosažení příkazu v iterátoru je vrácen výraz a aktuální umístění v kódu je uchováno. Spuštění je restartováno z tohoto umístění při příštím volání iterátoru.
Další informace najdete v tématu iterátory (Visual Basic).
Následující příklad používá metodu iterátoru. Metoda iterátoru má Yield příkaz, který je uvnitř ... Další smyčka V ListEvenNumbers metodě Každá iterace For Each těla příkazu vytvoří volání metody iterátoru, která pokračuje k dalšímu Yield příkazu.
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