Megosztás a következőn keresztül:


Gyűjtemények (Visual Basic)

Számos alkalmazás esetében létre szeretné hozni és kezelni szeretné a kapcsolódó objektumok csoportjait. Az objektumok csoportosításának két módja van: objektumtömbök létrehozásával és objektumgyűjtemények létrehozásával.

A tömbök akkor hasznosak, ha rögzített számú erősen beírt objektumot hoznak létre és dolgoznak fel. A tömbökről további információt a Tömbök című témakörben talál.

A gyűjtemények rugalmasabb módot biztosítanak az objektumcsoportok használatához. A tömbökkel ellentétben a használatban lévő objektumok csoportja dinamikusan növekedhet és zsugorodhat, ahogy az alkalmazás igényei változnak. Egyes gyűjtemények esetében kulcsokat rendelhet a gyűjteménybe helyezett bármely objektumhoz, hogy gyorsan lekérhesse az objektumot a kulccsal.

A gyűjtemény egy osztály, ezért deklarálnia kell az osztály egy példányát, mielőtt elemeket vehet fel a gyűjteménybe.

Ha a gyűjtemény csak egy adattípus elemeit tartalmazza, használhatja a névtér egyik osztályát System.Collections.Generic . Egy általános gyűjtemény a típusbiztonságot kényszeríti ki, hogy ne lehessen más adattípust hozzáadni. Amikor egy elemet egy általános gyűjteményből kér le, nem kell meghatároznia az adattípusát, és nem kell átalakítani azt.

Feljegyzés

A jelen témakör példái közé tartoznak az Import utasítások a névterekhez és System.Linq a System.Collections.Generic névterekhez.

Egyszerű gyűjtemény használata

Az ebben a szakaszban szereplő példák az általános List<T> osztályt használják, amely lehetővé teszi az objektumok erősen gépelt listájának használatát.

Az alábbi példa egy sztringlistát hoz létre, majd végigfuttat a sztringeken egy Minden... Következő utasítás.

' 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

Ha a gyűjtemény tartalma előre ismert, a gyűjtemény inicializálásához használhat gyűjtemény inicializálót . További információt a Gyűjtemény inicializálói című témakörben talál.

Az alábbi példa megegyezik az előző példával, kivéve, hogy a gyűjtemény inicializálója elemeket ad hozzá a gyűjteményhez.

' 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

Használhatja a következőhöz: Következő utasítás a For Each gyűjteményen keresztüli iterálásra vonatkozó utasítás helyett. Ezt úgy érheti el, hogy a gyűjtemény elemeit az index pozíciója alapján éri el. Az elemek indexe 0-nál kezdődik, és az elemszám mínusz 1 lesz.

Az alábbi példa a gyűjtemény elemein halad végig ahelyett, hogy a következőt használjuk For…NextFor 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

Az alábbi példa eltávolít egy elemet a gyűjteményből az eltávolítandó objektum megadásával.

' 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

Az alábbi példa eltávolítja az elemeket egy általános listából. Ahelyett, hogy egy For Each utasítást, egy For... Következő utasítás, amely szerint az iterálás csökkenő sorrendben történik. Ennek az az oka, hogy a metódus az RemoveAt eltávolított elemek után alacsonyabb indexértéket eredményez.

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

A benne lévő List<T>elemek típusához saját osztályt is definiálhat. Az alábbi példában a Galaxy kódban a használt List<T> osztály van definiálva.

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

Gyűjteménytípusok

A .NET-keretrendszer számos gyakori gyűjteményt biztosít. Minden gyűjteménytípust egy adott célra terveztek.

A gyakori gyűjteményosztályok némelyikét ebben a szakaszban ismertetjük:

System.Collections.Generic osztályok

Általános gyűjteményt a névtér egyik osztályával System.Collections.Generic hozhat létre. Az általános gyűjtemény akkor hasznos, ha a gyűjtemény minden eleme ugyanazzal az adattípussal rendelkezik. Az általános gyűjtemények erős gépelést kényszerítenek ki, mert csak a kívánt adattípust engedélyezik.

Az alábbi táblázat a névtér gyakran használt osztályait sorolja fel System.Collections.Generic :

Osztály Leírás
Dictionary<TKey,TValue> A kulcs/érték párok gyűjteménye, amelyek a kulcs alapján vannak rendszerezve.
List<T> Az index által elérhető objektumok listáját jelöli. Listák keresésére, rendezésére és módosítására használható módszereket biztosít.
Queue<T> Az objektumok első be- és kifelé (FIFO) gyűjteményét jelöli.
SortedList<TKey,TValue> Kulcs/érték párok gyűjteményét jelöli, amelyek kulcs szerint vannak rendezve a társított IComparer<T> implementáció alapján.
Stack<T> Az objektumok utolsó be- és kifelé (LIFO) gyűjteményét jelöli.

További információ: Gyakori gyűjteménytípusok, Gyűjteményosztály kiválasztása és System.Collections.Generic.

System.Collections.Egyidejű osztályok

A .NET-keretrendszer 4-ben vagy újabbban a System.Collections.Concurrent névtérben lévő gyűjtemények hatékony szálbiztos műveleteket biztosítanak a több szálból származó gyűjteményelemek eléréséhez.

A névtérben lévő System.Collections.Concurrent osztályokat a megfelelő típusok helyett kell használni a System.Collections.GenericSystem.Collections névterekben, amikor egyszerre több szál is hozzáfér a gyűjteményhez. További információ: Thread-Széf Collections and System.Collections.Concurrent.

A névtér egyes osztályai a System.Collections.Concurrent következőkBlockingCollection<T>: , ConcurrentQueue<T>ConcurrentDictionary<TKey,TValue>és ConcurrentStack<T>.

System.Collections-osztályok

A névtér osztályai System.Collections nem kifejezetten gépelt objektumokként, hanem típusobjektumként Objecttárolják az elemeket.

Amikor csak lehetséges, a névtérben vagy a System.Collections.GenericSystem.Collections.Concurrent névtérben lévő általános gyűjteményeket kell használnia a névtér régi típusai System.Collections helyett.

Az alábbi táblázat felsorolja a névtérben gyakran használt osztályok némelyikét System.Collections :

Osztály Leírás
ArrayList Olyan objektumtömböt jelöl, amelynek mérete igény szerint dinamikusan növekszik.
Hashtable A kulcs kivonatkódja alapján rendezett kulcs/érték párok gyűjteményét jelöli.
Queue Az objektumok első be- és kifelé (FIFO) gyűjteményét jelöli.
Stack Az objektumok utolsó be- és kifelé (LIFO) gyűjteményét jelöli.

A System.Collections.Specialized névtér speciális és erősen gépelt gyűjteményosztályokat biztosít, például csak sztringgyűjteményeket, csatolt listákat és hibrid szótárakat.

Visual Basic Collection Class

A Visual Basic Collection osztály használatával numerikus index vagy kulcs használatával érheti el a gyűjteményelemeket String . A gyűjteményobjektumhoz kulcs megadásával vagy anélkül is hozzáadhat elemeket. Ha kulcs nélküli elemet ad hozzá, a hozzá való hozzáféréshez a numerikus indexet kell használnia.

A Visual Basic Collection osztály minden elemét típusként Objecttárolja, így bármilyen adattípusú elemet hozzáadhat. Nincs védelem a nem megfelelő adattípusok hozzáadása ellen.

A Visual Basic Collection osztály használatakor a gyűjtemény első elemének indexe 1. Ez eltér a .NET-keretrendszer gyűjteményosztályoktól, amelyek kezdő indexe 0.

Amikor csak lehetséges, a Visual Basic Collection osztály helyett a System.Collections.Generic névtérben vagy a System.Collections.Concurrent névtérben lévő általános gyűjteményeket kell használnia.

További információ: Collection.

Kulcs/érték párok gyűjteményének implementálása

Az Dictionary<TKey,TValue> általános gyűjtemény lehetővé teszi a gyűjtemény elemeinek elérését az egyes elemek kulcsával. A szótár minden egyes hozzáadása egy értékből és a hozzá tartozó kulcsból áll. Az érték lekérése a kulcsával gyors, mert az Dictionary osztály kivonattáblázatként van implementálva.

Az alábbi példa létrehoz egy gyűjteményt Dictionary , és egy utasítással For Each végigvezeti a szótáron.

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

Ha ehelyett gyűjtemény inicializálót szeretne használni a Dictionary gyűjtemény létrehozásához, cserélje le a BuildDictionary metódusokat a AddToDictionary következő metódusra.

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

Az alábbi példa az ContainsKey elem kulcs szerinti gyors megkeresésének módszerét és Item[] tulajdonságát Dictionary használja. A Item tulajdonság lehetővé teszi a gyűjtemény egy elemének elérését a elementselements(symbol) Visual Basic kódjának használatával.

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

Az alábbi példa ehelyett a metódust használja egy TryGetValue elem kulcs szerinti gyors megkeresésére.

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

Gyűjtemény elérése a LINQ használatával

A LINQ (Language-Integrated Query) a gyűjtemények eléréséhez használható. A LINQ-lekérdezések szűrési, rendezési és csoportosítási képességeket biztosítanak. További információ: A LINQ használatának első lépései a Visual Basicben.

Az alábbi példa linq-lekérdezést futtat egy általános List. A LINQ-lekérdezés egy másik gyűjteményt ad vissza, amely tartalmazza az eredményeket.

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

Gyűjtemény rendezése

Az alábbi példa egy gyűjtemény rendezési eljárását szemlélteti. A példa az osztály egy adott osztályban List<T>tárolt példányait Car rendezi. Az Car osztály implementálja az IComparable<T> interfészt, ami megköveteli a metódus implementálását CompareTo .

A metódus minden CompareTo hívása egyetlen összehasonlítást végez, amelyet a rendszer a rendezéshez használ. A metódus felhasználó által írt kódja egy CompareTo értéket ad vissza az aktuális objektum és egy másik objektum összehasonlításához. A visszaadott érték kisebb, mint nulla, ha az aktuális objektum kisebb, mint a másik objektum, nagyobb, mint nulla, ha az aktuális objektum nagyobb, mint a másik objektum, és nulla, ha egyenlő. Ez lehetővé teszi, hogy kódban definiálja a nagyobb, kisebb és egyenlő feltételek feltételeit.

A metódusban az ListCarscars.Sort() utasítás rendezi a listát. A metódus meghívása SortList<T> automatikusan meghívja a CompareTo metódust a CarList.

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

Egyéni gyűjtemény definiálása

A gyűjteményt a felület vagy IEnumerable a IEnumerable<T> felület implementálásával határozhatja meg. További információ: Gyűjtemény számbavétele.

Bár egyéni gyűjteményeket is definiálhat, általában jobb, ha inkább az .NET-keretrendszer részét képező gyűjteményeket használja, amelyekről a témakör korábbi, Gyűjteménytípusok című szakaszában olvashat.

Az alábbi példa egy egyéni gyűjteményosztályt AllColorshatároz meg. Ez az osztály implementálja az IEnumerable interfészt, amely megköveteli a metódus implementálását GetEnumerator .

A GetEnumerator metódus az osztály egy példányát ColorEnumerator adja vissza. ColorEnumeratorimplementálja az IEnumerator interfészt, amely megköveteli a tulajdonság, MoveNext a metódus és Reset a Current metódus implementálását.

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átorok

Az iterátor használatával egyéni iterációt hajthat végre egy gyűjteményen keresztül. Az iterátor lehet módszer vagy get tartozék. Az iterátor egy Hozam utasítással egyenként adja vissza a gyűjtemény minden elemét.

Iterátort hívhat meg minden egyes... Következő utasítás. A hurok minden iterációja For Each meghívja az iterátort. Yield Amikor az iterátor egy utasítást ér el, a rendszer visszaad egy kifejezést, és megtartja a kód aktuális helyét. A végrehajtás a következő alkalommal, amikor az iterátort meghívják, újraindul a végrehajtás.

További információ: Iterators (Visual Basic).

Az alábbi példa egy iterátormetódust használ. Az iterátor metódusnak van egy Yield utasítása, amely a For... Következő ciklus. A metódusban az ListEvenNumbers utasítás törzsének minden iterációja For Each létrehoz egy hívást az iterátor metódushoz, amely a következő Yield utasításra folytatódik.

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

Lásd még