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…Next
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
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
System.Collections.Concurrent Osztályok
System.Collections Osztályok
Visual Basic
Collection
osztály
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 Object
tá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 Object
tá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 elements
elements(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 ListCars
cars.Sort()
utasítás rendezi a listát. A metódus meghívása SortList<T> automatikusan meghívja a CompareTo
metódust a Car
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
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 AllColors
hatá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. ColorEnumerator
implementá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
- Gyűjtemény inicializálói
- Programozási fogalmak (Visual Basic)
- Option Strict Utasítás
- LINQ to Objects (Visual Basic)
- Párhuzamos LINQ (PLINQ)
- Gyűjtemények és adatstruktúrák
- Gyűjteményosztály kiválasztása
- Összehasonlítások és rendezés gyűjteményeken belül
- Mikor érdemes általános gyűjteményeket használni?