Partager via


Collections (Visual Basic)

Pour de nombreuses applications, vous souhaitez créer et gérer des groupes d’objets associés. Il existe deux façons de regrouper des objets : en créant des tableaux d’objets et en créant des collections d’objets.

Les tableaux sont les plus 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 un moyen plus flexible d’utiliser des groupes d’objets. Contrairement aux tableaux, le groupe d’objets avec lequel vous travaillez peut croître et réduire dynamiquement à mesure que les besoins de l’application changent. Pour certaines collections, vous pouvez affecter une clé à n’importe quel objet que vous avez placé dans la collection afin de pouvoir récupérer rapidement l’objet à l’aide de la clé.

Une collection est une classe. Vous devez donc déclarer une instance de la classe avant de pouvoir ajouter des éléments à cette collection.

Si votre collection contient des éléments d’un seul type de données, vous pouvez utiliser l’une des classes de l’espace System.Collections.Generic de noms. Une collection générique applique la sécurité des types afin qu’aucun autre type de données ne puisse être ajouté à celui-ci. Lorsque vous récupérez un élément d’une collection générique, vous n’avez pas besoin de déterminer son type de données ou de le convertir.

Remarque

Pour obtenir les exemples de cette rubrique, incluez des instructions Imports pour les espaces de noms et System.Linq les System.Collections.Generic espaces de noms.

Utilisation d’une collection simple

Les exemples de cette section utilisent la classe générique List<T> , qui vous permet d’utiliser une liste fortement typée d’objets.

L’exemple suivant crée une liste de chaînes, puis effectue une itération dans les chaînes à l’aide d’un For Each... Instruction suivante .

' 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 à l’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, sauf 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 un For... Instruction suivante au lieu d’une For Each instruction pour itérer dans une collection. Pour ce faire, accédez aux éléments de collection par 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 For…Next 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 des éléments d’une liste générique. Au lieu d’une For Each instruction, un For... L’instruction suivante qui itère dans l’ordre décroissant est utilisée. Cela est dû au fait que la méthode fait en sorte que les RemoveAt éléments après un élément supprimé aient une valeur d’index inférieure.

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 dans le List<T>, vous pouvez également définir votre propre classe. Dans l’exemple suivant, la Galaxy classe utilisée par le List<T> code est définie.

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

De nombreuses collections courantes sont fournies par le .NET Framework. Chaque type de collection est conçu à des fins spécifiques.

Certaines des classes de collection courantes sont décrites dans cette section :

System.Collections.Generic Classes

Vous pouvez créer une collection générique à l’aide de l’une des classes de l’espace System.Collections.Generic de noms. Une collection générique est utile lorsque chaque élément de la collection a le même type de données. Une collection générique applique un type fort en autorisant uniquement l’ajout du type de données souhaité.

Le tableau suivant répertorie certaines des classes fréquemment utilisées de l’espace System.Collections.Generic de noms :

classe Descriptif
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 pour rechercher, trier et modifier des listes.
Queue<T> Représente une première collection d’objets (FIFO) en premier sorti.
SortedList<TKey,TValue> Représente une collection de paires clé/valeur triées par clé en fonction de l’implémentation associée IComparer<T> .
Stack<T> Représente une dernière collection d’objets (LIFO) en premier sorti.

Pour plus d’informations, consultez Types de collection couramment utilisés, sélection d’une classe de collection et System.Collections.Generic.

System.Collections.Concurrent Classes

Dans .NET Framework 4 ou version ultérieure, les collections de l’espace System.Collections.Concurrent de noms fournissent des opérations thread-safe efficaces pour accéder aux éléments de collection à partir de plusieurs threads.

Les classes de l’espace System.Collections.Concurrent de noms doivent être utilisées au lieu des types correspondants dans les espaces de noms et System.Collections des System.Collections.Generic espaces de noms chaque fois que plusieurs threads accèdent simultanément à la collection. Pour plus d’informations, consultez Thread-Safe Collections et System.Collections.Concurrent.

Certaines classes incluses dans l’espace System.Collections.Concurrent de noms sont BlockingCollection<T>, ConcurrentDictionary<TKey,TValue>, ConcurrentQueue<T>et ConcurrentStack<T>.

System.Collections Classes

Les classes de l’espace System.Collections de noms ne stockent pas d’éléments en tant qu’objets spécifiquement typés, mais en tant qu’objets de type Object.

Dans la mesure du possible, vous devez utiliser les collections génériques dans l’espace System.Collections.Generic de noms ou l’espace System.Collections.Concurrent de noms au lieu des types hérités dans l’espace System.Collections de noms.

Le tableau suivant répertorie certaines des classes fréquemment utilisées dans l’espace System.Collections de noms :

classe Descriptif
ArrayList Représente un tableau d’objets dont la taille est augmentée dynamiquement 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 première collection d’objets (FIFO) en premier sorti.
Stack Représente une dernière collection d’objets (LIFO) en premier sorti.

L’espace System.Collections.Specialized de noms fournit des classes de collection spécialisées et fortement typées, telles que des collections de chaînes uniquement et des dictionnaires liés et hybrides.

Classe de collection Visual Basic

Vous pouvez utiliser la classe Visual Basic Collection pour accéder à un élément de collection à l’aide d’un index numérique ou d’une String clé. Vous pouvez ajouter des éléments à un objet de collection avec ou sans spécifier de 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 en tant que type Object. Vous pouvez donc ajouter un élément de n’importe quel type de données. Il n’existe aucune protection contre les types de données inappropriés ajoutés.

Lorsque vous utilisez la classe Visual Basic Collection , le premier élément d’une collection a un index de 1. Cela diffère des classes de collection .NET Framework pour lesquelles l’index de départ est 0.

Dans la mesure du possible, vous devez utiliser les collections génériques dans l’espace System.Collections.Generic de noms ou l’espace System.Collections.Concurrent de noms au lieu de la classe Visual Basic Collection .

Pour plus d’informations, consultez Collection.

Implémentation d’une collection de paires clé/valeur

La Dictionary<TKey,TValue> collection générique 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 rapide, car la Dictionary classe est implémentée en tant que table de hachage.

L’exemple suivant crée une Dictionary collection et itère dans le dictionnaire à l’aide d’une For Each instruction.

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

Pour utiliser plutôt un initialiseur de collection pour générer la Dictionary collection, vous pouvez remplacer les méthodes et AddToDictionary les BuildDictionary méthodes 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 ContainsKey méthode et la Item[] propriété de Dictionary rechercher rapidement un élément par clé. La Item propriété vous permet d’accéder à un élément de la collection à l’aide elements du elements(symbol) code 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 plutôt la TryGetValue méthode 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 Prise en main de LINQ en Visual Basic.

L’exemple suivant exécute une requête LINQ sur un générique List. 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 Car classe stockées dans un List<T>. La Car classe implémente l’interface IComparable<T> , ce qui nécessite que la CompareTo méthode soit implémentée.

Chaque appel à la méthode effectue une comparaison unique utilisée pour le CompareTo tri. Le code écrit par l’utilisateur dans la CompareTo méthode 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érieur à zéro si l’objet actuel est supérieur à l’autre objet et zéro s’il est égal à celui-ci. Cela vous permet de définir dans le code les critères supérieurs, inférieurs et égaux.

Dans la méthode, l’instruction ListCarscars.Sort() trie la liste. Cet appel à la Sort méthode des List<T> causes de l’appel automatique de la CompareTo méthode pour les Car objets du 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 ou IEnumerable l’interfaceIEnumerable<T>. Pour plus d’informations, consultez Énumération d’une collection.

Bien que vous puissiez définir une collection personnalisée, il est généralement préférable d’utiliser plutôt les collections incluses dans le .NET Framework, qui 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 nécessite que la GetEnumerator méthode soit implémentée.

La GetEnumerator méthode retourne une instance de la ColorEnumerator classe. ColorEnumeratorimplémente l’interfaceIEnumerator, ce qui nécessite que la propriété, MoveNext la méthode et Reset la Current méthode soient implémentées.

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

Itérateurs

Un itérateur est utilisé pour effectuer une itération personnalisée sur une collection. Un itérateur peut être une méthode ou un get accesseur. Un itérateur utilise une instruction Yield pour renvoyer chaque élément de la collection un à la fois.

Vous appelez un itérateur à l’aide d’un for Each... Instruction suivante . Chaque itération de la For Each boucle appelle l’itérateur. Lorsqu’une Yield instruction est atteinte dans l’itérateur, une expression est retournée et l’emplacement actuel dans le code est conservé. 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 d’itérateur. La méthode itérateur a une Yield instruction qui se trouve à l’intérieur d’un For... Boucle suivante . Dans la ListEvenNumbers méthode, chaque itération du corps de l’instruction For Each crée un appel à la méthode itérateur, qui passe à l’instruction suivante Yield .

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