Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Para muchas aplicaciones, se desea crear y administrar grupos de objetos relacionados. Hay dos maneras de agrupar objetos: mediante la creación de matrices de objetos y mediante la creación de colecciones de objetos.
Las matrices son más útiles para crear y trabajar con un número fijo de objetos fuertemente tipados. Para obtener información sobre las matrices, vea Matrices.
Las colecciones proporcionan una manera más flexible de trabajar con grupos de objetos. A diferencia de las matrices, el grupo de objetos con los que trabaja puede crecer y reducirse dinámicamente a medida que cambian las necesidades de la aplicación. Para algunas colecciones, puede asignar una clave a cualquier objeto que coloque en la colección para que pueda recuperar rápidamente el objeto mediante la clave .
Una colección es una clase, por lo que debe declarar una instancia de la clase para poder agregar elementos a esa colección.
Si la colección contiene solo elementos de un tipo de datos, puede usar una de las clases del System.Collections.Generic espacio de nombres . Una colección genérica exige la seguridad de tipos para que no se pueda agregar ningún otro tipo de datos. Al recuperar un elemento de una colección genérica, no es necesario determinar su tipo de datos ni convertirlo.
Nota:
En los ejemplos de este tema, incluya las instrucciones Imports (Importaciones) para los espacios de nombres System.Collections.Generic
y System.Linq
.
Uso de una colección simple
Los ejemplos de esta sección usan la clase genérica List<T> , que permite trabajar con una lista fuertemente tipada de objetos.
En el ejemplo siguiente se crea una lista de cadenas y, a continuación, se recorre las cadenas mediante la instrucción 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 el contenido de una colección se conoce de antemano, puede usar un inicializador de colección para inicializar la colección. Para obtener más información, vea Inicializadores de colección.
El ejemplo siguiente es el mismo que el ejemplo anterior, excepto que se usa un inicializador de colección para agregar elementos a la colección.
' 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
Puede usar una instrucción For…Next en lugar de una instrucción For Each
para recorrer una colección. Para ello, acceda a los elementos de la colección por la posición del índice. El índice de los elementos comienza en 0 y termina en el recuento de elementos menos 1.
En el ejemplo siguiente se recorre en iteración los elementos de una colección mediante For…Next
en lugar 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
En el ejemplo siguiente se quita un elemento de la colección especificando el objeto que se va a quitar.
' 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
En el ejemplo siguiente se quitan elementos de una lista genérica. En lugar de una For Each
instrucción, se utiliza una instrucción For... Next que itera en orden descendente. Esto se debe a que el método hace que los RemoveAt elementos después de un elemento quitado tengan un valor de índice inferior.
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
Para el tipo de elementos de List<T>, puede también definir su propia clase. En el ejemplo siguiente, la Galaxy
clase usada por List<T> se define en el código .
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
Tipos de colecciones
Muchas colecciones comunes las proporciona .NET Framework. Cada tipo de colección está diseñado para un propósito específico.
Algunas de las clases de colección comunes se describen en esta sección:
System.Collections.Generic Clases
System.Collections Clases
Clase de Visual Basic
Collection
Clases System.Collections.Generic
Puede crear una colección genérica mediante una de las clases del System.Collections.Generic espacio de nombres . Una colección genérica es útil cuando cada elemento de la colección tiene el mismo tipo de datos. Una colección genérica aplica una escritura segura al permitir que solo se agregue el tipo de datos deseado.
En la tabla siguiente se enumeran algunas de las clases usadas con frecuencia del System.Collections.Generic espacio de nombres:
Clase | Descripción |
---|---|
Dictionary<TKey,TValue> | Representa una colección de pares clave-valor que se organizan en función de la clave. |
List<T> | Representa una lista de objetos a los que puede acceder el índice. Proporciona métodos para buscar, ordenar y modificar listas. |
Queue<T> | Representa una colección FIFO (primero en entrar, primero en salir) de objetos. |
SortedList<TKey,TValue> | Representa una colección de pares clave-valor ordenados por clave en función de la implementación asociada IComparer<T> . |
Stack<T> | Representa una colección LIFO (último en entrar, primero en salir) de objetos. |
Para obtener más información, vea Tipos de colección usados habitualmente, Seleccionar una clase de colección y System.Collections.Generic.
Clases System.Collections.Concurrent
En .NET Framework 4 o posterior, las colecciones del espacio de nombres System.Collections.Concurrent proporcionan operaciones eficaces y seguras para subprocesos con el fin de obtener acceso a los elementos de la colección desde varios subprocesos.
Las clases del espacio de nombres System.Collections.Concurrent deben utilizarse en lugar de los tipos correspondientes de los espacios de nombres System.Collections.Generic y System.Collections cuando varios subprocesos acceden a la colección de forma simultánea. Para obtener más información, vea ColeccionesThread-Safe y System.Collections.Concurrent.
Algunas clases incluidas en el System.Collections.Concurrent espacio de nombres son BlockingCollection<T>, ConcurrentDictionary<TKey,TValue>, ConcurrentQueue<T>y ConcurrentStack<T>.
Clases System.Collections
Las clases del System.Collections espacio de nombres no almacenan elementos como objetos con tipo específico, sino como objetos de tipo Object
.
Siempre que sea posible, debes usar las colecciones genéricas en el espacio de nombres System.Collections.Generic o el espacio de nombres System.Collections.Concurrent en lugar de los tipos heredados en el espacio de nombres System.Collections
.
En la tabla siguiente se enumeran algunas de las clases usadas con frecuencia en el System.Collections
espacio de nombres:
Clase | Descripción |
---|---|
ArrayList | Representa una matriz de objetos cuyo tamaño se incrementa dinámicamente según sea necesario. |
Hashtable | Representa una colección de pares de clave y valor que se organizan por código hash de la clave. |
Queue | Representa una colección FIFO (primero en entrar, primero en salir) de objetos. |
Stack | Representa una colección LIFO (último en entrar, primero en salir) de objetos. |
El System.Collections.Specialized espacio de nombres proporciona clases de colección especializadas y tipadas de forma rígida, como colecciones de solo cadenas de caracteres y diccionarios híbridos y listas enlazadas.
Clase de colección de Visual Basic
Puede usar la clase de Visual Basic Collection para tener acceso a un elemento de colección mediante un índice numérico o una String
clave. Puede agregar elementos a un objeto de colección con o sin especificar una clave. Si agrega un elemento sin una clave, debe usar su índice numérico para acceder a él.
La clase de Visual Basic Collection
almacena todos sus elementos como tipo Object
, por lo que puede agregar un elemento de cualquier tipo de datos. No hay ninguna protección contra los tipos de datos inapropiados que se agregan.
Cuando se usa la clase de Visual Basic Collection
, el primer elemento de una colección tiene un índice de 1. Esto difiere de las clases de colección de .NET Framework, para las que el índice inicial es 0.
Siempre que sea posible, debe usar las colecciones genéricas del espacio de nombres System.Collections.Generic o del espacio de nombres System.Collections.Concurrent en lugar de la clase de Visual Basic Collection
.
Para obtener más información, consulte Collection.
Implementación de una colección de pares clave-valor
La Dictionary<TKey,TValue> colección genérica permite acceder a los elementos de una colección mediante la clave de cada elemento. Cada adición al diccionario consta de un valor y su clave asociada. Recuperar un valor mediante su clave es rápido porque la Dictionary
clase se implementa como una tabla hash.
En el ejemplo siguiente se crea una colección Dictionary
y se recorre en iteración el diccionario usando una instrucción 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
Para usar en su lugar un inicializador de colección para compilar la Dictionary
colección, puede reemplazar los BuildDictionary
métodos y AddToDictionary
por el método siguiente.
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
En el ejemplo siguiente se usa el ContainsKey método y la Item[] propiedad de Dictionary
para buscar rápidamente un elemento por clave. La Item
propiedad permite tener acceso a un elemento de la elements
colección mediante el elements(symbol)
código de 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
En su lugar, en el ejemplo siguiente se usa el TryGetValue método para buscar rápidamente un elemento por clave.
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 de LINQ para acceder a una colección
LINQ (Language-Integrated Query) se puede usar para acceder a las colecciones. Las consultas LINQ proporcionan funcionalidades de filtrado, ordenación y agrupación. Para obtener más información, vea Introducción a LINQ en Visual Basic.
En el ejemplo siguiente se ejecuta una consulta LINQ en un genérico List
. La consulta LINQ devuelve una colección diferente que contiene los resultados.
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
Ordenar una colección
En el ejemplo siguiente se muestra un procedimiento para ordenar una colección. En el ejemplo se ordenan instancias de la Car
clase que se almacenan en .List<T> La Car
clase implementa la IComparable<T> interfaz , que requiere que se implemente el CompareTo método .
Cada llamada al CompareTo método realiza una única comparación que se usa para la ordenación. El código escrito por el usuario en el CompareTo
método devuelve un valor para cada comparación del objeto actual con otro objeto. El valor devuelto es menor que cero si el objeto actual es menor que el otro objeto, mayor que cero si el objeto actual es mayor que el otro objeto y cero si son iguales. Esto permite definir en el código los criterios de mayor que, menor que e igual.
En el ListCars
método , la cars.Sort()
instrucción ordena la lista. Esta llamada al método Sort de List<T> hace que el método CompareTo
se invoque automáticamente para los objetos Car
en el 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
Definición de una colección personalizada
Puede definir una colección implementando la IEnumerable<T> interfaz o IEnumerable . Para obtener más información, vea Enumerar una colección.
Aunque puede definir una colección personalizada, normalmente es mejor usar las colecciones que se incluyen en .NET Framework, que se describen en Tipos de colecciones anteriormente en este tema.
En el ejemplo siguiente se define una clase de colección personalizada denominada AllColors
. Esta clase implementa la IEnumerable interfaz , que requiere que se implemente el GetEnumerator método .
El GetEnumerator
método devuelve una instancia de la ColorEnumerator
clase .
ColorEnumerator
implementa la interfaz IEnumerator, que requiere que se implementen la propiedad Current, el método MoveNext y el método 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
Iteradores
Un iterador se usa para realizar una iteración personalizada en una colección. Un iterador puede ser un método o un descriptor de acceso get
. Un iterador usa una instrucción Yield para devolver cada elemento de la colección uno a uno.
Se llama a un iterador mediante una instrucción For Each...Next. Cada iteración del For Each
bucle llama al iterador. Cuando se alcanza una Yield
instrucción en el iterador, se devuelve una expresión y se conserva la ubicación actual en el código. La ejecución se reinicia desde esa ubicación la próxima vez que se llame al iterador.
Para obtener más información, vea Iteradores (Visual Basic) .
En el ejemplo siguiente se usa un método iterador. El método del iterador tiene una instrucción Yield
que se encuentra dentro de un bucle For...Next. En el ListEvenNumbers
método, cada iteración del cuerpo de la For Each
instrucción crea una llamada al método iterador, que avanza a la siguiente instrucción 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
Consulte también
- Inicializadores de colección
- Conceptos de programación (Visual Basic)
- Option Strict (instrucción)
- LINQ to Objects (Visual Basic)
- LINQ paralelo (PLINQ)
- Colecciones y estructuras de datos
- Seleccionar una clase de colección
- Comparaciones y ordenaciones dentro de colecciones
- Cuándo usar colecciones genéricas