Collections (Visual Basic)
Pour de nombreuses applications, vous voulez créer et gérer des groupes d’objets connexes. Il existe deux manières de grouper des objets : en créant des tableaux d’objets ou des collections d’objets.
Les tableaux s’avèrent particulièrement utiles pour créer et utiliser un nombre fixe d’objets fortement typés. Pour plus d’informations sur les tableaux, consultez Tableaux.
Les collections offrent plus de souplesse quand il s’agit d’utiliser des groupes d’objets. Contrairement aux tableaux, le groupe d’objets que vous utilisez peut être développé et réduit de manière dynamique selon les modifications de l’application. Pour certaines collections, vous pouvez assigner une clé à un objet que vous placez dans la collection pour vous permettre de récupérer rapidement l’objet à l’aide de la clé.
Une collection est une classe, vous devez déclarer une instance de la classe avant de pouvoir ajouter des éléments à la collection.
Si votre collection contient des éléments d’un seul type de données, vous pouvez utiliser une des classes dans l’espace de noms System.Collections.Generic. Une collection générique applique la cohérence des types pour éviter qu’un autre type puisse y être ajouté. Quand vous récupérez un élément d’une collection générique, il n’est pas utile de déterminer son type de données ou de le convertir.
Notes
Pour les exemples de cette rubrique, ajoutez des instructions Imports pour les espaces de noms System.Collections.Generic
et System.Linq
.
Utilisation d’une collection simple
Les exemples de cette section utilisent la classe List<T> générique, qui vous permet d’utiliser une liste d’objets fortement typée.
L’exemple suivant crée une liste de chaînes, puis itère au sein des chaînes à l’aide d’une instruction For Each…Next.
' 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
Si le contenu d’une collection est connu d’avance, vous pouvez utiliser un initialiseur de collection pour initialiser la collection. Pour plus d’informations, consultez Initialiseurs de collection.
L’exemple suivant est identique à l’exemple précédent, à la différence qu’un initialiseur de collection est utilisé pour ajouter des éléments à la collection.
' 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
Vous pouvez utiliser une instruction For…Next au lieu d’une instruction For Each
pour itérer au sein d’une collection. Pour cela, accédez aux éléments de la collection à la position d’index. L’index des éléments commence à 0 et se termine au nombre d’éléments moins 1.
L’exemple suivant itère au sein des éléments d’une collection à l’aide de For…Next
au lieu de 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
L’exemple suivant supprime un élément de la collection en spécifiant l’objet à supprimer.
' 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
L’exemple suivant supprime les éléments d’une liste générique. À la place d’une instruction For Each
, une instruction For…Next, qui itère dans l’ordre décroissant, est utilisée. En effet, avec la méthode RemoveAt, les éléments après l’élément supprimé ont une valeur d’index moins élevée.
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
Pour le type d’éléments de List<T>, vous pouvez également définir votre propre classe. Dans l’exemple suivant, la classe Galaxy
qui est utilisée par List<T> est définie dans le code.
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
Types de collections
Plusieurs collections courantes sont fournies par le .NET Framework. Chaque type de collection est conçu dans un but spécifique.
Certaines des classes de collection courantes sont décrites dans cette section :
Classes System.Collections.Generic
Classes System.Collections.Concurrent
Classes System.Collections
Classe
Collection
Visual Basic
Classes System.Collections.Generic
Vous pouvez créer une collection générique en utilisant l’une des classes dans l’espace de noms System.Collections.Generic. Une collection générique est utile quand chaque élément de la collection a le même type de données. Une collection générique applique un typage fort en autorisant uniquement l’ajout des types de données souhaités.
Le tableau suivant liste quelques classes de l’espace de noms System.Collections.Generic fréquemment utilisées :
Classe | Description |
---|---|
Dictionary<TKey,TValue> | Représente une collection de paires clé/valeur organisées en fonction de la clé. |
List<T> | Représente une liste d’objets accessibles par index. Fournit des méthodes de recherche, de tri et de modification de listes. |
Queue<T> | Représente une collection d’objets premier entré, premier sorti (FIFO). |
SortedList<TKey,TValue> | Représente une collection de paires clé/valeur triées par clé en fonction de l'implémentation IComparer<T> associée. |
Stack<T> | Représente une collection d’objets dernier entré, premier sorti (LIFO). |
Pour plus d’informations, consultez Types de collections couramment utilisés, Sélection d’une classe de collection et System.Collections.Generic.
Classes System.Collections.Concurrent
Dans .NET Framework 4 ou ultérieur, les collections de l’espace de noms System.Collections.Concurrent fournissent des opérations thread-safe efficaces pour accéder aux éléments de collection à partir de plusieurs threads.
Les classes de l’espace de noms System.Collections.Concurrent doivent être utilisées à la place des types correspondants dans les espaces de noms System.Collections.Generic et System.Collections chaque fois que plusieurs threads accèdent simultanément à la collection. Pour plus d’informations, consultez Collections thread-safe et System.Collections.Concurrent.
Certaines classes incluses dans l’espace de noms System.Collections.Concurrent sont BlockingCollection<T>, ConcurrentDictionary<TKey,TValue>, ConcurrentQueue<T> et ConcurrentStack<T>.
Classes System.Collections
Les classes de l’espace de noms System.Collections ne stockent pas les éléments comme des objets spécifiquement typés, mais comme des objets de type Object
.
Si possible, vous devez utiliser les collections génériques dans l’espace de noms System.Collections.Generic ou System.Collections.Concurrent à la place des types hérités de l’espace de noms System.Collections
.
Le tableau suivant répertorie certaines des classes fréquemment utilisées de l’espace de noms System.Collections
:
Classe | Description |
---|---|
ArrayList | Représente un tableau d’objets dont la taille est augmentée de manière dynamique selon les besoins. |
Hashtable | Représente une collection de paires clé/valeur qui sont organisées en fonction du code de hachage de la clé. |
Queue | Représente une collection d’objets premier entré, premier sorti (FIFO). |
Stack | Représente une collection d’objets dernier entré, premier sorti (LIFO). |
L’espace de noms System.Collections.Specialized fournit des classes de collection spécialisées et fortement typées, telles que les collections à chaîne unique et les dictionnaires de liste liée et hybrides.
Classe de la collection Visual Basic
Vous pouvez utiliser la classe Visual Basic Collection pour accéder à une collection d’éléments à l’aide d’un index numérique ou d’une clé String
. Vous pouvez ajouter des éléments à un objet de collection en spécifiant ou non une clé. Si vous ajoutez un élément sans clé, vous devez utiliser son index numérique pour y accéder.
La classe Visual Basic Collection
stocke tous ses éléments sous le type Object
, de sorte que vous pouvez ajouter un élément de n’importe quel type de données. Il n’existe aucun dispositif de protection contre l’ajout de types de données inappropriés.
Quand vous utilisez la classe Visual Basic Collection
, le premier élément d’une collection a un index égal à 1. Ce n’est pas le cas pour les classes de collection .NET Framework, pour lesquelles l’index de départ est 0.
Si possible, vous devez utiliser les collections génériques dans l’espace de noms System.Collections.Generic ou System.Collections.Concurrent à la place de la classe Visual Basic Collection
.
Pour plus d’informations, consultez Collection.
Implémentation d’une collection de paires clé/valeur
La collection générique Dictionary<TKey,TValue> vous permet d’accéder aux éléments d’une collection à l’aide de la clé de chaque élément. Chaque ajout au dictionnaire se compose d’une valeur et de sa clé associée. La récupération d’une valeur à l’aide de sa clé est très rapide, car la classe Dictionary
est implémentée en tant que table de hachage.
L’exemple suivant crée une collection Dictionary
et itère au sein du dictionnaire à l’aide d’une instruction For Each
.
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
Au lieu d’utiliser un initialiseur de collection pour générer la collection Dictionary
, vous pouvez remplacer les méthodes BuildDictionary
et AddToDictionary
par la méthode suivante.
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
L’exemple suivant utilise la méthode ContainsKey et la propriété Item[] de Dictionary
pour rechercher rapidement un élément par clé. La propriété Item
vous permet d’accéder à un élément de la collection elements
à l’aide du code elements(symbol)
en 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
L’exemple suivant utilise à la place la méthode TryGetValue pour rechercher rapidement un élément par clé.
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
Utilisation de LINQ pour accéder à une collection
LINQ (Language-Integrated Query) peut être utilisé pour accéder aux collections. Les requêtes LINQ fournissent des fonctionnalités de filtrage, de classement et de regroupement. Pour plus d’informations, consultez Bien démarrer avec LINQ en Visual Basic.
L’exemple suivant exécute une requête LINQ sur un List
générique. La requête LINQ retourne une autre collection qui contient les résultats.
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
Tri d’une collection
L’exemple suivant illustre une procédure de tri d’une collection. L’exemple trie les instances de la classe Car
stockées dans un List<T>. La classe Car
implémente l’interface IComparable<T>, ce qui implique l’implémentation de la méthode CompareTo.
Chaque appel à la méthode CompareTo effectue une comparaison unique qui est utilisée pour le tri. Le code écrit par l’utilisateur dans la méthode CompareTo
retourne une valeur pour chaque comparaison de l’objet actuel avec un autre objet. La valeur retournée est inférieure à zéro si l’objet actuel est inférieur à l’autre objet, supérieure à zéro l’objet actuel est supérieur à l’autre et égale à zéro s’ils sont égaux. Cela vous permet de définir dans le code les critères définissant « supérieur à », « inférieur à » et « égal à ».
Dans la méthode ListCars
, l’instruction cars.Sort()
trie la liste. Cet appel à la méthode Sort de List<T> entraîne l’appel automatique de la méthode CompareTo
pour les objets Car
dans 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
Définition d’une collection personnalisée
Vous pouvez définir une collection en implémentant l’interface IEnumerable<T> ou IEnumerable. Pour plus d’informations, consultez Énumération d’une collection.
Même si vous pouvez définir une collection personnalisée, il est généralement préférable d’utiliser les collections comprises dans le .NET Framework, lesquelles sont décrites dans Types de collections, plus haut dans cette rubrique.
L’exemple suivant définit une classe de collection personnalisée nommée AllColors
. Cette classe implémente l’interface IEnumerable, ce qui implique l’implémentation de la méthode GetEnumerator.
La méthode GetEnumerator
retourne une instance de la classe ColorEnumerator
. ColorEnumerator
implémente l’interface IEnumerator, ce qui implique l’implémentation de la propriété Current, la méthode MoveNext et la méthode Reset.
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
Iterators
Un itérateur est utilisé pour exécuter une itération personnalisée sur une collection. Un itérateur peut être une méthode ou un accesseur get
. Un itérateur utilise une instruction Yield pour retourner chaque élément de la collection un par un.
Vous appelez un itérateur en utilisant une instruction For Each…Next. Chaque itération de la boucle For Each
appelle l’itérateur. Quand une instruction Yield
est atteinte dans l’itérateur, une expression est retournée et la localisation actuelle dans le code est retenue. L’exécution est redémarrée à partir de cet emplacement la prochaine fois que l’itérateur est appelé.
Pour plus d’informations, consultez Itérateurs (Visual Basic).
L'exemple suivant utilise une méthode Iterator. La méthode Iterator a une instruction Yield
qui se trouve à l’intérieur d’une boucle For…Next. Dans la méthode ListEvenNumbers
, chaque itération du corps de l’instruction For Each
crée un appel à la méthode Iterator, qui continue sur l’instruction Yield
suivante.
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
Voir aussi
- Initialiseurs de collection
- Concepts de programmation (Visual Basic)
- Option Strict Statement
- LINQ to Objects (Visual Basic)
- Parallel LINQ (PLINQ)
- Collections et structures de données
- Sélection d’une classe de collection
- Comparaisons et tris dans les collections
- Quand utiliser les collections génériques