Een belangrijk onderdeel van vrijwel iedere applicatie zijn collecties. Of u nou werkt met Arrays, Strings, lijsten, Dictionaries of DataTables, collecties zijn overal in uw software aanwezig.
De Array kennen we waarschijnlijk allemaal. Een Array is een collectie met een vast aantal objecten. Hoewel Arrays erg snel zijn werken ze niet gemakkelijk. Vaak moet u precies weten wat waar in een Array gaat om er optimaal mee te kunnen werken. Let er op dat Arrays (net als alle andere collectie types .NET) een zero-based index hebben. Dit betekent dat het eerste item op index 0 zit, de tweede op index 1 enz.

  1: ' Maak een array waar 10 items in kunnen.
  2: ' Vul de array met 10 Integers.
  3: Dim nummers(9) As Integer
  4: For i As Integer = 0 To 9
  5:    nummers(i) = i + 1
  6: Next
  7: 
  8: ' Voeg een 11de toe.
  9: Array.Resize(nummers, 11)
 10: nummers(10) = 11

Het inserten of deleten zonder oude waarden te overschrijven is dusdanig ingewikkeld dat ik ze hier niet ga bespreken. Makkelijker is om gebruik te maken van een ArrayList. De ArrayList, samen met andere collectie typen, bevindt zich in de System.Collections Namespace.

  1: Dim arrList As New System.Collections.ArrayList
  2: For i As Integer = 1 To 10
  3:    arrList.Add(i)
  4: Next
  5: 
  6: ' Voeg een 11de toe. Geen Resize nodig (dit gebeurt onder de motorkap)!
  7: arrList.Add(11)
  8: 
  9: ' Insert na de 5 (op index 6).
 10: arrList.Insert(6, 12)
 11: 
 12: ' Verwijder de 12 weer.
 13: arrList.Remove(12)
 14: 
 15: ' Het uitlezen en overschrijven van items op index kan ook nog steeds.
 16: ' Geeft 3 terug.
 17: Dim i As Integer = arrList(2)
 18: ' Overschrijft 3 met 30.
 19: arrList(2) = 30

Uiteraard zitten hier wat 'gotchas' aan vast. Zo verwijdert Remove enkel de eerste instantie van een 12 die in de lijst staat. Zouden we dus twee maal een 12 in de lijst hebben staan dan word enkel de eerste verwijderd.

Wat echter het grootste nadeel is aan een ArrayList is dat deze 'weakly typed' is. Dit betekent dat we er werkelijk alles in kunnen stoppen wat we maar willen, Integers, Strings, andere ArrayLists, noem maar op. Dit is gevaarlijk omdat u er misschien van uit gaat dat er enkel Integers in een collectie zitten. Als er dan via een programmeer fout tóch een String in zit dan krijgt u hier designtime geen melding van, maar crasht uw programma runtime.

  1: ' We maken een ArrayList en stoppen hier enkele Integers in
  2: ' door gebruik te maken van een overloaded constructor.
  3: Dim arrList As New System.Collections.ArrayList({1, 2, 3})
  4: ' Voeg later nog een Integer toe.
  5: arrList.Add(4)
  6: ' Voeg een String toe.
  7: arrList.Add("Hallo")
  8: ' Tel alle waarden in de lijst op.
  9: Dim totaal As Integer = 0
 10: For Each value As Object In arrList
 11:    ' Een hoop unboxing.
 12:    ' Geeft een Exception op de waarde "Hallo".
 13:    totaal = totaal + CInt(value)
 14: Next

Nog een nadeel hieraan is dat value types (Integers, Decimals, Booleans...) 'geboxed' moeten worden. Dit betekent dat deze waarden in een Object 'gepropt' worden, wat extra overhead met zich meebrengt.

  1: ' Hier vindt 'boxing' plaats omdat een Boolean een value type is.
  2: Dim o As Object = True
  3: ' Hier vindt 'unboxing' plaats, de Boolean moet weer uit het Object 'getrokken' worden.
  4: Dim b As Boolean = CBool(o)
  5: 
  6: ' Hier vindt geen 'boxing' plaats omdat een ArrayList geen value, maar een reference type is.
  7: Dim o As Object = New ArrayList
  8: ' Hier vindt dus ook geen unboxing plaats, enkel een conversie. 
  9: DirectCast(o, ArrayList)

Door deze weakly typed aanpak en de performance overhead van boxing en unboxing raad ik u dan ook aan om nooit een ArrayList of andere collectie uit de System.Collections Namespace te gebruiken als u alternatieven heeft.

Gelukkig zijn er sinds het .NET Framework 2.0 alternatieven voor weakly typed collecties! Deze bevinden zich in de System.Collections.Generic Namespace. Van deze Namespace kunt u standaard gebruik maken in een nieuw VB project (in tegenstelling tot System.Collections die u zelf zal moeten uittypen of Importeren).
De collecties in de System.Collections.Generic maken gebruik van een techniek die 'Generics' genoemd wordt. Zo vind u hier bijvoorbeeld de List(Of T) klasse. De T is hier de 'generic' en kan vervangen worden door wat u maar wilt (T staat voor Type).

  1: Dim list As New List(Of Integer)
  2: list.Add(1)
  3: list.Add(2)
  4: list.Add(3)
  5: ' De volgende regel geeft een error!
  6: List.Add("Hallo")

U ziet dat door aan te geven dat mijn List enkel Integers mag bevatten ik geen String toe kan voegen. Het omgekeerde geld ook.

  1: Dim list As New List(Of String)
  2: list.Add("Generics")
  3: list.Add("zijn")
  4: list.Add("super!")
  5: ' De volgende regel geeft een error!
  6: list.Add(1)

Daarnaast bevat de List(Of T) klasse ook bewerkingen zoals Remove, RemoveAll, Insert, Contains, Sort etc.

  1: ' Maak een nieuwe lijst met Integers door een overloaded constructor te gebruiken.
  2: Dim list As New List(Of Integer)({4, 7, 2, 9, 5})
  3: list.Add(3)
  4: list.Add(2)
  5: ' Insert een 8 aan het begin van de lijst.
  6: list.Insert(0, 8)
  7: ' Gebruik een 'lambda' expressie om alle 2en uit de lijst te verwijderen.
  8: list.RemoveAll(Function(i) i = 2)
  9: ' Sorteer de lijst.
 10: list.Sort()

Het voordeel van Generics is dus dat u nog tijdens designtime fouten op kan lossen. Bovendien vindt er geen boxing en unboxing meer plaats omdat de compiler voortaan weet of een bepaald object een value type of een reference type is.
Allicht komt u klassen tegen met meer dan één Generic type, bijvoorbeeld de Dictionary(Of TKey, TValue). In dit geval vervangt u alle Generics met wat u maar wilt. Na de declaratie van het type zullen overal waar Tkey en TValue gebruikt worden nu instanties van de aangegeven typen gebruikt moeten worden.

  1: Dim dict As New Dictionary(Of Integer, String)
  2: dict.Add(1, "Hallo")
  3: dict.Add(2, "Nogmaals hallo")

De Dictionary(Of TKey, TValue) is een collectie die waarden koppelt aan unieke sleutelwaarden. De sleutelwaarden moeten uniek zijn, de gewone waarden niet. Een Dictionary(Of TKey, TValue) is overigens (bijna) een List(Of KeyValuePair(Of TKey, TValue)). Over een dictionary itereren (met For Each) werkt dan ook als volgt.

  1: Dim dict As New Dictionary(Of Integer, String)
  2: dict.Add(1, "Nog")
  3: dict.Add(2, "een")
  4: dict.Add(3, "test")
  5: ' Dubbele waarde, dit mag.
  6: dict.Add(4, "test")
  7: 
  8: For Each pair As KeyValuePair(Of Integer, String) In dict
  9:       Console.WriteLine(String.Format("{0} – {1}{2}", pair.Key.ToString, pair.Value, Environment.Newline))
 10: Next
 11: 
 12: ' Output:
 13: ' 1 – Nog
 14: ' 2 – een
 15: ' 3 – test
 16: ' 4 – test

Zoals ik al zei is het toevoegen van dubbele sleutelwaarden niet toegestaan. U krijgt hier pas tijdens runtime foutmeldingen op, dus let op!

  1: Dim dict As New Dictionary(Of Integer, String)
  2: dict.Add(1, "Goed")
  3: dict.Add(2, "Goed")
  4: ' Voeg nogmaals sleutelwaarde 2 toe.
  5: dict.Add(2, "Fout!")

Het opvragen of overschrijven van waarden op index gaat net iets anders in een Dictionary. Dit gebeurt namelijk op sleutelwaarde in plaats van index.

  1: Dim dict As New Dictionary(Of String, String)
  2: dict.Add("Hallo", "Dit is leuk!")
  3: dict.Add("Vaarwel", "Dit is treurig!")
  4: 
  5: ' Dit geeft de waarde "Dit is leuk!" terug.
  6: Dim s As String = dict("Hallo")
  7: ' Overschrijft "Dit is treurig!".
  8: dict("Vaarwel") = "Ohnee, dit is ook leuk!"

De List(Of T) en Dictionary(Of Tkey, TValue) werken over het algemeen redelijk intuïtief en zijn erg breed toepasbaar. U zult dan ook na enige oefening niet beter meer weten dan om een Generic collectie te gebruiken met alle voordelen van dien. De voordelen van Generic collecties ten opzichte van hun niet generieke tegenhangers zijn designtime controle op type en snelheid. Als u over een jaar uw code nog eens zal moeten herzien zult u zich dus ook niet meer af hoeven vragen wat er ook alweer voor objecten in een bepaalde collectie zitten. Dit staat nu vast!

De documentatie van List(Of T) en Dictionary(Of Tkey, TValue) staan redelijk uitgebreid op MSDN. U kunt daar dan ook goed terecht voor meer uitleg en code voorbeelden.
System.Collections.Generic Namespace op MSDN
List(Of T) op MSDN
Dictionary(Of TKey, TValue) op MSDN

Succes!