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:

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

Viz také