Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Per molte applicazioni, è necessario creare e gestire gruppi di oggetti correlati. Esistono due modi per raggruppare gli oggetti: creando matrici di oggetti e creando raccolte di oggetti.
Le matrici sono più utili per la creazione e l'uso di un numero fisso di oggetti fortemente tipizzati. Per informazioni sulle matrici, vedere Matrici.
Le raccolte offrono un modo più flessibile per lavorare con gruppi di oggetti. A differenza delle matrici, il gruppo di oggetti con cui si lavora può aumentare e ridurre dinamicamente in base alle esigenze dell'applicazione. Per alcune raccolte, è possibile assegnare una chiave a qualsiasi oggetto inserito nella raccolta in modo da poter recuperare rapidamente l'oggetto usando la chiave .
Una raccolta è una classe, pertanto è necessario dichiarare un'istanza della classe prima di poter aggiungere elementi a tale raccolta.
Se la raccolta contiene elementi di un solo tipo di dati, è possibile usare una delle classi dello spazio dei nomi System.Collections.Generic. Una raccolta generica applica la sicurezza dei tipi in modo che nessun altro tipo di dati possa essere aggiunto. Quando si recupera un elemento da una raccolta generica, non è necessario determinarne il tipo di dati o convertirlo.
Annotazioni
Per gli esempi in questo argomento, includere le istruzioni Imports per gli spazi dei nomi System.Collections.Generic
e System.Linq
.
Uso di una raccolta semplice
Gli esempi in questa sezione usano la classe generica List<T> , che consente di usare un elenco di oggetti fortemente tipizzato.
L'esempio seguente crea una lista di stringhe e quindi itera sulle stringhe usando un'istruzione 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
Se il contenuto di una raccolta è noto in anticipo, è possibile utilizzare un inizializzatore di raccolta per inizializzare la raccolta. Per altre informazioni, vedere Inizializzatori di raccolta.
L'esempio seguente è uguale all'esempio precedente, ad eccezione di un inizializzatore di raccolta usato per aggiungere elementi alla raccolta.
' 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
È possibile utilizzare un'istruzione For…Next anziché un'istruzione For Each
per scorrere una raccolta. A tale scopo, accedere agli elementi della raccolta in base alla posizione dell'indice. L'indice degli elementi inizia da 0 e termina con il conteggio degli elementi meno 1.
Nel seguente esempio si scorre gli elementi di una raccolta usando For…Next
invece di 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
Nell'esempio seguente viene rimosso un elemento dalla raccolta specificando l'oggetto da rimuovere.
' 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
Nell'esempio seguente vengono rimossi elementi da un elenco generico. Invece di un'istruzione For Each
, viene usata un'istruzione For…Next che esegue l'iterazione in ordine decrescente. Questo perché il RemoveAt metodo fa sì che gli elementi dopo un elemento rimosso abbiano un valore di indice inferiore.
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
Per il tipo di elementi in List<T>, è anche possibile definire la propria classe. Nell'esempio seguente la Galaxy
classe usata da List<T> è definita nel codice .
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
Tipi di raccolte
Molte raccolte comuni vengono fornite da .NET Framework. Ogni tipo di raccolta è progettato per uno scopo specifico.
Alcune classi di raccolte comuni sono descritte in questa sezione:
System.Collections.Generic Classi
System.Collections Classi
Classe Visual Basic
Collection
Classi System.Collections.Generic
È possibile creare una raccolta generica usando una delle classi nello spazio dei nomi System.Collections.Generic. Una raccolta generica è utile quando ogni elemento della raccolta ha lo stesso tipo di dati. Una raccolta generica applica la digitazione avanzata consentendo l'aggiunta solo del tipo di dati desiderato.
Nella tabella seguente sono elencate alcune delle classi usate di frequente del System.Collections.Generic namespace.
Classe | Descrizione |
---|---|
Dictionary<TKey,TValue> | Rappresenta una raccolta di coppie chiave/valore organizzate in base alla chiave. |
List<T> | Rappresenta un elenco di oggetti a cui è possibile accedere in base all'indice. Fornisce metodi per la ricerca, l'ordinamento e la modifica degli elenchi. |
Queue<T> | Rappresenta una collezione di oggetti di tipo FIFO (First In, First Out). |
SortedList<TKey,TValue> | Rappresenta una raccolta di coppie chiave/valore ordinate in base alla chiave in base all'implementazione associata IComparer<T> . |
Stack<T> | Rappresenta un insieme LIFO (Last In, First Out) di oggetti. |
Per altre informazioni, vedere Tipi di raccolta comunemente usati, Selezione di una classe di raccolta e System.Collections.Generic.
Classi di System.Collections.Concurrent
In .NET Framework 4 o versione successiva, le raccolte nello System.Collections.Concurrent spazio dei nomi forniscono operazioni thread-safe efficienti per l'accesso agli elementi della raccolta da più thread.
Le classi nello spazio dei nomi System.Collections.Concurrent devono essere usate anziché i tipi corrispondenti negli spazi dei nomi System.Collections.Generic e System.Collections quando più thread accedono contemporaneamente alla raccolta. Per altre informazioni, vedere CollezioniThread-Safe e System.Collections.Concurrent.
Alcune classi incluse nel namespace System.Collections.Concurrent sono BlockingCollection<T>, ConcurrentDictionary<TKey,TValue>, ConcurrentQueue<T>, e ConcurrentStack<T>.
Classi System.Collections
Le classi nello spazio dei nomi System.Collections non archiviano gli elementi come oggetti con tipi specifici, ma come oggetti di tipo Object
.
Quando possibile, è consigliabile usare le raccolte generiche nello spazio dei nomi System.Collections.Generic o nello spazio dei nomi System.Collections.Concurrent anziché i tipi legacy nello spazio dei nomi System.Collections
.
Nella tabella seguente sono elencate alcune delle classi usate di frequente nello spazio dei nomi System.Collections
.
Classe | Descrizione |
---|---|
ArrayList | Rappresenta una matrice di oggetti le cui dimensioni vengono aumentate dinamicamente in base alle esigenze. |
Hashtable | Rappresenta una raccolta di coppie chiave/valore organizzate in base al codice hash della chiave. |
Queue | Rappresenta una collezione di oggetti di tipo FIFO (First In, First Out). |
Stack | Rappresenta un insieme LIFO (Last In, First Out) di oggetti. |
Lo System.Collections.Specialized spazio dei nomi fornisce classi di raccolte specializzate e fortemente tipate, ad esempio raccolte di sola stringa e dizionari collegati e ibridi.
Classe di raccolta di Visual Basic
È possibile utilizzare la classe Visual Basic Collection per accedere a un elemento della raccolta utilizzando un indice numerico o una String
chiave. È possibile aggiungere elementi a un oggetto raccolta con o senza specificare una chiave. Se si aggiunge un elemento senza una chiave, è necessario usare il relativo indice numerico per accedervi.
La classe Visual Basic Collection
archivia tutti i relativi elementi come tipo Object
, in modo da poter aggiungere un elemento di qualsiasi tipo di dati. Non esiste alcuna protezione contro i tipi di dati inappropriati aggiunti.
Quando si utilizza la classe Visual Basic Collection
, il primo elemento di una raccolta ha un indice pari a 1. Ciò è diverso dalle classi di raccolta di .NET Framework, per cui l'indice iniziale è 0.
Quando possibile, è consigliabile usare le raccolte generiche nello System.Collections.Generic spazio dei nomi o nello System.Collections.Concurrent spazio dei nomi anziché nella classe Visual Basic Collection
.
Per altre informazioni, vedere Collection.
Implementazione di una raccolta di coppie chiave/valore
La Dictionary<TKey,TValue> raccolta generica consente di accedere agli elementi di una raccolta usando la chiave di ogni elemento. Ogni aggiunta al dizionario è costituita da un valore e dalla chiave associata. Il recupero di un valore tramite la relativa chiave è rapido perché la Dictionary
classe viene implementata come tabella hash.
L'esempio seguente crea una raccolta Dictionary
e itera attraverso il dizionario usando un'istruzione 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
Per usare invece un inizializzatore di raccolta per compilare la Dictionary
raccolta, è possibile sostituire i BuildDictionary
metodi e AddToDictionary
con il metodo seguente.
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
Nell'esempio seguente viene utilizzato il ContainsKey metodo e la Item[] proprietà di Dictionary
per trovare rapidamente un elemento in base alla chiave. La Item
proprietà consente di accedere a un elemento nella elements
raccolta usando il elements(symbol)
codice in 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
Nell'esempio seguente viene invece usato il TryGetValue metodo per trovare rapidamente un elemento in base alla chiave.
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
Uso di LINQ per accedere a una collezione
LINQ (Language-Integrated Query) può essere usato per accedere alle raccolte. Le query LINQ offrono funzionalità di filtro, ordinamento e raggruppamento. Per altre informazioni, vedere Introduzione a LINQ in Visual Basic.
Nell'esempio seguente viene eseguita una query LINQ su un oggetto generico List
. La query LINQ restituisce un insieme diverso che contiene i risultati.
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
Ordinamento di una raccolta
Nell'esempio seguente viene illustrata una routine per l'ordinamento di una raccolta. Nell'esempio vengono ordinate le istanze della Car
classe archiviate in un oggetto List<T>. La Car
classe implementa l'interfaccia IComparable<T>, che richiede l'implementazione del metodo CompareTo.
Ogni chiamata al CompareTo metodo esegue un singolo confronto usato per l'ordinamento. Il codice scritto dall'utente nel CompareTo
metodo restituisce un valore per ogni confronto dell'oggetto corrente con un altro oggetto. Il valore restituito è minore di zero se l'oggetto corrente è minore dell'altro oggetto, maggiore di zero se l'oggetto corrente è maggiore dell'altro oggetto e zero se sono uguali. In questo modo è possibile definire nel codice i criteri per maggiore di, minore di e uguale.
ListCars
Nel metodo l'istruzione cars.Sort()
ordina l'elenco. Questa chiamata al metodo Sort di List<T> fa sì che il metodo CompareTo
venga chiamato automaticamente per gli oggetti Car
in 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
Definizione di una raccolta personalizzata
È possibile definire una raccolta implementando l'interfaccia IEnumerable<T> o IEnumerable . Per altre informazioni, vedere Enumerazione di una raccolta.
Sebbene sia possibile definire una raccolta personalizzata, in genere è preferibile usare le raccolte incluse in .NET Framework, descritte in Tipi di raccolte più indietro in questo argomento.
Nell'esempio seguente viene definita una classe di raccolta personalizzata denominata AllColors
. Questa classe implementa l'interfaccia IEnumerable, che richiede che il metodo GetEnumerator sia implementato.
Il GetEnumerator
metodo restituisce un'istanza della ColorEnumerator
classe .
ColorEnumerator
implementa l'interfaccia IEnumerator, che richiede l'implementazione della proprietà Current, del metodo MoveNext e del metodo 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
Iteratori
Un iteratore viene usato per eseguire un'iterazione personalizzata su una raccolta. Un iteratore può essere un metodo o un get
accessor. Un iteratore usa un'istruzione yield return per restituire ogni elemento della raccolta, uno alla volta.
Per utilizzare un iteratore, usare l'istruzione For Each...Next. Ogni iterazione del For Each
ciclo chiama l'iteratore. Quando viene raggiunta un'istruzione Yield
nell'iteratore, viene restituita un'espressione e viene mantenuta la posizione corrente nel codice. L'esecuzione viene riavviata da tale posizione alla successiva chiamata dell'iteratore.
Per altre informazioni, vedere Iteratori (Visual Basic).
Nell'esempio seguente viene utilizzato un metodo iteratore. Il metodo iteratore ha un'istruzione Yield
che si trova all'interno di un ciclo For…Next.
ListEvenNumbers
Nel metodo ogni iterazione del corpo dell'istruzione For Each
crea una chiamata al metodo iteratore, che procede con l'istruzione successivaYield
.
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
Vedere anche
- Inizializzatori di raccolta
- Concetti relativi alla programmazione (Visual Basic)
- Istruzione Option Strict
- LINQ to Objects (Visual Basic)
- LINQ parallelo (PLINQ)
- Raccolte e strutture di dati
- Selezione di una classe di raccolta
- Confronti e ordinamenti all'interno di raccolte
- Quando usare raccolte generiche