Para muchas aplicaciones, puede que desee crear y administrar grupos de objetos relacionados. Existen dos formas de agrupar objetos: mediante la creación de matrices de objetos y con la creación de colecciones de objetos.
Las matrices son muy ú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 el que trabaja puede aumentar y reducirse de manera dinámica a medida que cambian las necesidades de la aplicación. Para algunas colecciones, puede asignar una clave a cualquier objeto que incluya en la colección para, de este modo, recuperar rápidamente el objeto con la clave.
Una colección es una clase, por lo que debe declarar una instancia de la clase para poder agregar elementos a dicha colección.
Si la colección contiene elementos de un solo tipo de datos, puede usar una de las clases del espacio de nombres System.Collections.Generic. Una colección genérica cumple la seguridad de tipos para que ningún otro tipo de datos se pueda agregar a ella. Cuando recupera un elemento de una colección genérica, no tiene que 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 le permite trabajar con una lista de objetos fuertemente tipados.
En el ejemplo siguiente se crea una lista de cadenas y luego se recorren en iteración mediante una instrucción For Each...Next (Para cada...Siguiente).
VB
' Create a list of strings.Dim salmons AsNew List(OfString)
salmons.Add("chinook")
salmons.Add("coho")
salmons.Add("pink")
salmons.Add("sockeye")
' Iterate through the list.ForEach salmon AsStringIn 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.
VB
' Create a list of strings by using a' collection initializer.Dim salmons AsNew List(OfString) From
{"chinook", "coho", "pink", "sockeye"}
ForEach salmon AsStringIn 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 en iteración una colección. Esto se consigue con el acceso a los elementos de la colección mediante la posición de índice. El índice de los elementos comienza en 0 y termina en el número de elementos menos 1.
El ejemplo siguiente recorre en iteración los elementos de una colección mediante For…Next en lugar de For Each.
VB
Dim salmons AsNew List(OfString) From
{"chinook", "coho", "pink", "sockeye"}
For index = 0To salmons.Count - 1
Console.Write(salmons(index) & " ")
Next'Output: chinook coho pink sockeye
El ejemplo siguiente quita un elemento de la colección especificando el objeto que se quitará.
VB
' Create a list of strings by using a' collection initializer.Dim salmons AsNew List(OfString) From
{"chinook", "coho", "pink", "sockeye"}
' Remove an element in the list by specifying' the object.
salmons.Remove("coho")
ForEach salmon AsStringIn salmons
Console.Write(salmon & " ")
Next'Output: chinook pink sockeye
El ejemplo siguiente quita elementos de una lista genérica. En lugar de una instrucción For Each, se usa una instrucción For...Next que procesa la iteración en orden descendente. Esto es porque el método RemoveAt hace que los elementos después de un elemento quitado tengan un valor de índice inferior.
VB
Dim numbers AsNew List(OfInteger) From
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
' Remove odd numbers.For index AsInteger = numbers.Count - 1To0Step-1If numbers(index) Mod2 = 1Then' Remove the element by specifying' the zero-based index in the list.
numbers.RemoveAt(index)
EndIfNext' 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>, también puede definir su propia clase. En el ejemplo siguiente, la clase Galaxy que usa List<T> se define en el código.
VB
PrivateSub IterateThroughList()
Dim theGalaxies AsNew 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}
}
ForEach theGalaxy In theGalaxies
With theGalaxy
Console.WriteLine(.Name & " " & .MegaLightYears)
EndWithNext' Output:' Tadpole 400' Pinwheel 25' Milky Way 0' Andromeda 3EndSubPublicClass Galaxy
PublicProperty Name AsStringPublicProperty MegaLightYears AsIntegerEndClass
Tipos de colecciones
.NET Framework proporciona muchas colecciones comunes. Cada tipo de colección está diseñado para un fin específico.
En esta sección se describen algunas de las clases de colecciones comunes:
Puede crear una colección genérica mediante una de las clases del espacio de nombres System.Collections.Generic. Una colección genérica es útil cuando todos los elementos de la colección tienen el mismo tipo. Una colección genérica exige el establecimiento de fuertes tipos al permitir agregar solo los tipos de datos deseados.
En la tabla siguiente se enumeran algunas de las clases usadas con frecuencia del espacio de nombres System.Collections.Generic:
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 no almacenan los elementos como objetos de tipo específico, sino como objetos del tipo Object.
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 los tipos heredados del espacio de nombres System.Collections.
En la siguiente tabla se enumeran algunas de las clases usadas con frecuencia en el espacio de nombres System.Collections:
Representa una colección de objetos de últimas entradas, primeras salidas (LIFO).
El espacio de nombres System.Collections.Specialized proporciona clases de colección especializadas y fuertemente tipadas como, por ejemplo, colecciones de solo cadena y diccionarios híbridos y de lista vinculada.
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 clave String. Puede agregar elementos a un objeto de colección especificando o sin especificar clave. Si agrega un elemento sin clave, debe usar su índice numérico para tener acceso a dicho elemento.
La clase de Visual Basic Collection almacena todos sus elementos como de tipo Object, por lo que puede agregar un elemento de cualquier tipo de datos. No hay ningún método de protección contra los tipos de datos inadecuados agregados.
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 cuales el índice inicial es 0.
Implementación de una colección de pares de clave/valor
La colección genérica Dictionary<TKey,TValue> le permite tener acceso a los elementos de una colección con la clave de cada elemento. Cada adición al diccionario consta de un valor y de su clave asociada. Recuperar un valor usando su clave es rápido porque la clase Dictionary 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.
VB
PrivateSub IterateThroughDictionary()
Dim elements As Dictionary(OfString, Element) = BuildDictionary()
ForEach kvp As KeyValuePair(OfString, Element) In elements
Dim theElement As Element = kvp.Value
Console.WriteLine("key: " & kvp.Key)
With theElement
Console.WriteLine("values: " & .Symbol & " " &
.Name & " " & .AtomicNumber)
EndWithNextEndSubPrivateFunction BuildDictionary() As Dictionary(OfString, Element)
Dim elements AsNew Dictionary(OfString, Element)
AddToDictionary(elements, "K", "Potassium", 19)
AddToDictionary(elements, "Ca", "Calcium", 20)
AddToDictionary(elements, "Sc", "Scandium", 21)
AddToDictionary(elements, "Ti", "Titanium", 22)
Return elements
EndFunctionPrivateSub AddToDictionary(ByVal elements As Dictionary(OfString, Element),
ByVal symbol AsString, ByVal name AsString, ByVal atomicNumber AsInteger)
Dim theElement AsNew Element
theElement.Symbol = symbol
theElement.Name = name
theElement.AtomicNumber = atomicNumber
elements.Add(Key:=theElement.Symbol, value:=theElement)
EndSubPublicClass Element
PublicProperty Symbol AsStringPublicProperty Name AsStringPublicProperty AtomicNumber AsIntegerEndClass
Para usar un inicializador de colección para compilar la colección Dictionary, puede reemplazar los métodos BuildDictionary y AddToDictionary por el método siguiente.
VB
PrivateFunction BuildDictionary2() As Dictionary(OfString, Element)
ReturnNew Dictionary(OfString, 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}}
}
EndFunction
En el ejemplo siguiente se usa el método ContainsKey y la propiedad Item[] de Dictionary para encontrar rápidamente un elemento por clave. La propiedad Item le permite tener acceso a un elemento de la colección elements usando el código elements(symbol) en Visual Basic.
VB
PrivateSub FindInDictionary(ByVal symbol AsString)
Dim elements As Dictionary(OfString, Element) = BuildDictionary()
If elements.ContainsKey(symbol) = FalseThen
Console.WriteLine(symbol & " not found")
ElseDim theElement = elements(symbol)
Console.WriteLine("found: " & theElement.Name)
EndIfEndSub
En el ejemplo siguiente se usa en su lugar el método TryGetValue para encontrar rápidamente un elemento por clave.
VB
PrivateSub FindInDictionary2(ByVal symbol AsString)
Dim elements As Dictionary(OfString, Element) = BuildDictionary()
Dim theElement As Element = NothingIf elements.TryGetValue(symbol, theElement) = FalseThen
Console.WriteLine(symbol & " not found")
Else
Console.WriteLine("found: " & theElement.Name)
EndIfEndSub
Uso de LINQ para tener acceso a una colección
LINQ (Language-Integrated Query) puede usar para tener acceso a las colecciones. Las consultas LINQ proporcionan capacidades de filtrado, ordenación y agrupación. Para más información, consulte Introducción a LINQ en Visual Basic.
El ejemplo siguiente ejecuta una consulta LINQ en una List genérica. La consulta LINQ devuelve otra colección que contiene los resultados.
VB
PrivateSub ShowLINQ()
Dim elements As List(Of Element) = BuildList()
' LINQ Query.Dim subset = From theElement In elements
Where theElement.AtomicNumber < 22OrderBy theElement.Name
ForEach theElement In subset
Console.WriteLine(theElement.Name & " " & theElement.AtomicNumber)
Next' Output:' Calcium 20' Potassium 19' Scandium 21EndSubPrivateFunction BuildList() As List(Of Element)
ReturnNew 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}}
}
EndFunctionPublicClass Element
PublicProperty Symbol AsStringPublicProperty Name AsStringPublicProperty AtomicNumber AsIntegerEndClass
Ordenar una colección
En el ejemplo siguiente se muestra un procedimiento para ordenar una colección. El ejemplo ordena las instancias de la clase Car que se almacenan en un List<T>. La clase Car implementa la interfaz IComparable<T>, que requiere implementar el método CompareTo.
Cada llamada al método CompareTo realiza una comparación única que se usa para la ordenación. El código escrito por el usuario en el método CompareTo 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 método ListCars, la instrucción cars.Sort() ordena la lista. Esta llamada al método Sort de List<T> hace que se llame automáticamente al método CompareTo para los objetos Car de List.
VB
PublicSub ListCars()
' Create some new cars.Dim cars AsNew 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.ForEach 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 car2EndSubPublicClass Car
Implements IComparable(Of Car)
PublicProperty Name AsStringPublicProperty Speed AsIntegerPublicProperty Color AsStringPublicFunction CompareTo(ByVal other As Car) AsInteger _
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.DimcompareAsIntegercompare = String.Compare(Me.Color, other.Color, True)
' If the colors are the same, compare the speeds.Ifcompare = 0Thencompare = Me.Speed.CompareTo(other.Speed)
' Use descending order for speed.compare = -compareEndIfReturncompareEndFunctionEndClass
Aunque puede definir una colección personalizada, es mejor usar las colecciones incluidas en .NET Framework. Estas colecciones se describen en la sección Tipos de colecciones de este tema.
En el siguiente ejemplo se define una clase de colección personalizada denominada AllColors. Esta clase implementa la interfaz IEnumerable que requiere implementar el método GetEnumerator.
El método GetEnumerator devuelve una instancia de la clase ColorEnumerator. ColorEnumerator implementa la interfaz IEnumerator, que requiere que la propiedad Current, el método MoveNext y el método Reset estén implementados.
VB
PublicSub ListColors()
Dim colors AsNew AllColors()
ForEach theColor As Color In colors
Console.Write(theColor.Name & " ")
Next
Console.WriteLine()
' Output: red blue greenEndSub' Collection class.PublicClass AllColors
Implements System.Collections.IEnumerable
Private _colors() As Color =
{
New Color With {.Name = "red"},
New Color With {.Name = "blue"},
New Color With {.Name = "green"}
}
PublicFunction GetEnumerator() As System.Collections.IEnumerator _
Implements System.Collections.IEnumerable.GetEnumerator
ReturnNew ColorEnumerator(_colors)
' Instead of creating a custom enumerator, you could' use the GetEnumerator of the array.'Return _colors.GetEnumeratorEndFunction' Custom enumerator.PrivateClass ColorEnumerator
Implements System.Collections.IEnumerator
Private _colors() As Color
Private _position AsInteger = -1PublicSubNew(ByVal colors() As Color)
_colors = colors
EndSubPublicReadOnlyProperty Current() AsObject _
Implements System.Collections.IEnumerator.Current
GetReturn _colors(_position)
EndGetEndPropertyPublicFunction MoveNext() AsBoolean _
Implements System.Collections.IEnumerator.MoveNext
_position += 1Return (_position < _colors.Length)
EndFunctionPublicSub Reset() Implements System.Collections.IEnumerator.Reset
_position = -1EndSubEndClassEndClass' Element class.PublicClass Color
PublicProperty Name AsStringEndClass
Iterators
Los iteradores se usan para efectuar 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 de uno en uno.
Se llama a un iterador mediante una instrucción For Each...Next. Cada iteración del bucle For Each llama al iterador. Cuando se alcanza una instrucción Yield 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 llama al iterador.
El siguiente ejemplo usa el método del iterador. El método del iterador tiene una instrucción Yield que se encuentra dentro de un bucle For...Next. En el método ListEvenNumbers, cada iteración del cuerpo de la instrucción For Each crea una llamada al método iterador, que continúa con la siguiente instrucción Yield.
VB
PublicSub ListEvenNumbers()
ForEach number AsIntegerIn EvenSequence(5, 18)
Console.Write(number & " ")
Next
Console.WriteLine()
' Output: 6 8 10 12 14 16 18EndSubPrivateIteratorFunction EvenSequence(
ByVal firstNumber AsInteger, ByVal lastNumber AsInteger) _
As IEnumerable(OfInteger)
' Yield even numbers in the range.For number = firstNumber To lastNumber
If number Mod2 = 0ThenYield number
EndIfNextEndFunction
El origen de este contenido se puede encontrar en GitHub, donde también puede crear y revisar problemas y solicitudes de incorporación de cambios. Para más información, consulte nuestra guía para colaboradores.
Comentarios de .NET
.NET es un proyecto de código abierto. Seleccione un vínculo para proporcionar comentarios:
Únase a la serie de reuniones para crear soluciones de inteligencia artificial escalables basadas en casos de uso reales con compañeros desarrolladores y expertos.