Tipos genéricos en Visual Basic (Visual Basic)

Un tipo genérico es un elemento de programación único que se adapta para realizar la misma funcionalidad en una variedad de tipos de datos. Cuando defina una clase o procedimiento genérico, no es necesario que defina una versión independiente para cada tipo de datos para el que desee llevar a cabo esa funcionalidad.

Un ejemplo análogo sería un juego de destornilladores con puntas extraíbles. Primero se inspecciona el tornillo que se debe apretar o aflojar y después se selecciona la punta adecuada para la cabeza del mismo (plana, en cruz o de estrella). Una vez insertada la punta correcta en el mango del destornillador, la acción realizada con el destornillador es exactamente la misma, es decir, girar el destornillador.

El juego de destornilladores es una herramienta genérica

Gráfico de un conjunto de destornilladores definido como herramienta genérica

Cuando defina un tipo genérico, lo puede parametrizar con uno o más tipos de datos. Esto permite al código que los utiliza ajustar los tipos de datos a sus necesidades. Su código puede declarar varios elementos de programación diferentes a partir del elemento genérico y cada uno de ellos actúa en un conjunto distinto de tipos de datos. Pero todos los elementos declarados funcionan con la misma lógica, independientemente de los tipos de datos que utilicen.

Por ejemplo, puede que desee crear y utilizar una clase de cola que funcione en un tipo de datos concreto como String. Puede declarar esa clase a partir de System.Collections.Generic.Queue<T>, como muestra el siguiente ejemplo.

Public stringQ As New System.Collections.Generic.Queue(Of String)

Ahora puede utilizar stringQ para trabajar exclusivamente con valores String. Dado que stringQ es específico para String en lugar de generalizarse para los valores Object, no tiene enlace en tiempo de ejecución ni conversión de tipos. Así se ahorra tiempo de ejecución y se reduce el número de errores en tiempo de ejecución.

Para obtener más información sobre cómo utilizar un tipo genérico, vea Cómo: Usar clases genéricas (Visual Basic).

Ejemplo de una clase genérica

El ejemplo siguiente muestra una estructura básica de una clase genérica.

Public Class classHolder(Of t)
    Public Sub processNewItem(ByVal newItem As t)
        Dim tempItem As t
        ' Insert code that processes an item of data type t.
    End Sub
End Class

En la estructura básica anterior, t es un parámetro de tipo, es decir, un marcador de posición para un tipo de datos que se proporcionará cuando declare la clase. En otra parte en su código, puede declarar distintas versiones de classHolder proporcionando diversos tipos de datos para t. En el ejemplo siguiente se muestran dos declaraciones así.

Public integerClass As New classHolder(Of Integer)
Friend stringClass As New classHolder(Of String)

Las instrucciones anteriores declaran clases construidas, en las que un tipo específico reemplaza el parámetro de tipo. Este reemplazo se propaga por todo el código existente dentro de la clase construida. El ejemplo siguiente muestra el aspecto que tiene el procedimiento processNewItem en integerClass.

Public Sub processNewItem(ByVal newItem As Integer)
    Dim tempItem As Integer
    ' Inserted code now processes an Integer item.
End Sub

Para obtener un ejemplo más completo, vea Cómo: Definir una clase que pueda proporcionar la misma funcionalidad en tipos de datos diferentes (Visual Basic).

Elementos de programación utilizables

Puede definir y utilizar clases, estructuras, interfaces, procedimientos y delegados de tipo genérico. Tenga en cuenta que .NET Framework define varias clases, estructuras e interfaces genéricas que normalmente representan los elementos genéricos utilizados. El espacio de nombres System.Collections.Generic proporciona diccionarios, listas, colas y pilas. Antes de definir su propio elemento genérico, vea si ya está disponible en System.Collections.Generic.

Los procedimientos no son tipos, pero puede definir y utilizar procedimientos genéricos. Vea Procedimientos genéricos en Visual Basic.

Ventajas de los tipos genéricos

Un tipo genérico sirve como base para declarar varios elementos de programación diferentes, cada uno de los cuales funciona en un tipo de datos concreto. Las alternativas a un tipo genérico son:

  1. Un tipo único que funciona en el tipo de datos Object.

  2. Un conjunto de versiones específicas de tipo del tipo, con cada versión codificada por separado y funcionando en un tipo de datos específico como String, Integer o un tipo definido por el usuario como, por ejemplo, customer.

Un tipo genérico presenta las ventajas siguientes sobre estas alternativas:

  • Seguridad de tipos. Los tipos genéricos fuerzan la comprobación de tipo en tiempo de compilación. Tipos basados en Object aceptan cualquier tipo de datos y debe escribir el código para comprobar si un tipo de datos de entrada es aceptable. Con los tipos genéricos, el compilador puede detectar los errores de coincidencia de tipos antes en tiempo de ejecución.

  • Rendimiento. Los tipos genéricos no tienen que aplicar la conversión boxing ni aplicar la conversión unboxing a los datos, porque cada uno de ellos está especializado para un tipo de datos. Las operaciones basadas en Object deben aplicar la conversión boxing para convertir los tipos de datos de entrada en Object y aplicar la conversión unboxing a los datos destinados para el resultado. Las conversiones boxing y unboxing reducen el rendimiento.

    Los tipos basados en Object también son enlazados en tiempo de ejecución, lo que significa que para tener acceso a sus miembros se requiere código adicional en tiempo de ejecución. Esto también reduce el rendimiento.

  • Consolidación del código. El código de un tipo genérico sólo ha de definirse una vez. Un conjunto de versiones específicas de tipo de un tipo debe replicar el mismo código en cada versión, con la única diferencia de que se trata del tipo de datos específico para esa versión. Con tipos genéricos, las versiones específicas de tipo se generan todas a partir del tipo genérico original.

  • Reutilización del código. El código que no depende de un tipo de datos determinado se puede reutilizar con distintos tipos de datos, si es genérico. Con frecuencia, se puede reutilizar incluso con un tipo de datos no previsto originalmente.

  • Compatibilidad con IDE. Cuando utilice un tipo construido a partir de un tipo genérico, Integrated Development Environment (IDE) puede proporcionarle más apoyo mientras programa el código. Por ejemplo, IntelliSense™ puede mostrarle las opciones específicas del tipo para un argumento a un constructor o método.

  • Algoritmos genéricos. Los algoritmos abstractos que son independientes del tipo son buenos candidatos para los tipos genéricos. Por ejemplo, un procedimiento genérico que ordena elementos mediante la interfaz IComparable se puede utilizar con cualquier tipo de datos que implemente IComparable.

Restricciones

Aunque el código de una definición de tipo genérico debe ser tan independiente del tipo como sea posible, puede que requiera una capacidad concreta de un tipo de datos proporcionado a su tipo genérico. Por ejemplo, si desea comparar dos elementos con el propósito de ordenar o intercalar, su tipo de datos debe implementar la interfaz IComparable. Puede forzar este requisito agregando una restricción al parámetro de tipo.

Ejemplo de una restricción

El ejemplo siguiente muestra una definición esquema de una clase con una restricción que exige al argumento de tipo que implemente IComparable.

Public Class itemManager(Of t As IComparable)
    ' Insert code that defines class members.
End Class

Si el código subsiguiente intenta construir una clase a partir de itemManager proporcionando un tipo que no implementa IComparable, el compilador señala un error.

Tipos de restricciones

Su restricción puede especificar los siguientes requisitos en cualquier combinación:

  • El argumento de tipo debe implementar una o más interfaces

  • El argumento de tipo debe ser, como máximo, del tipo de una clase o heredar de ella

  • El argumento de tipo debe exponer un constructor sin parámetros accesible al código que crea los objetos a partir del mismo

  • El argumento de tipo debe ser un tipo de referencia o un tipo de valor

Si necesita imponer más que un requisito, utilice una lista de restricciones separada por comas dentro de llaves ({ }). Para requerir un constructor accesible, incluya la palabra clave New (Operador, Visual Basic) en la lista. Para requerir un tipo de referencia, se debe incluir la palabra clave Class; para requerir un tipo de valor, incluya la palabra clave Structure.

Para obtener más información sobre restricciones, vea Lista de tipos (Visual Basic).

Ejemplo de varias restricciones

El ejemplo siguiente muestra una definición básica de una clase genérica con una lista de restricciones para el parámetro de tipo. En el código que crea una instancia de esta clase, el argumento de tipo debe implementar las interfaces IComparable y IDisposable, ser un tipo de referencia y exponer un constructor sin parámetros accesible.

Public Class thisClass(Of t As {IComparable, IDisposable, Class, New})
    ' Insert code that defines class members.
End Class

Condiciones importantes

Los tipos genéricos introducen y utilizan las condiciones siguientes:

  • Tipo genérico. Una definición de una clase, estructura, interfaz, procedimiento o delegado para las que proporciona al menos un tipo de datos cuando lo declara.

  • Parámetro de tipo. En una definición de tipo genérico, un marcador de posición para un tipo de datos proporcionado al declarar el tipo.

  • Argumento de tipo. Un tipo de datos concreto que reemplaza un parámetro de tipo cuando declara un tipo construido a partir de un tipo genérico.

  • Restricción. Una condición en un parámetro de tipo que restringe el argumento de tipo que se puede proporcionar. Una restricción puede requerir que el argumento de tipo debe implementar una interfaz concreta, ser una clase concreta o heredar de ella, tener un constructor sin parámetros accesible o ser un tipo de referencia o un tipo de valor. Puede combinar estas restricciones, pero puede especificar como máximo una clase.

  • Tipo construido. Una clase, estructura, interfaz, procedimiento o delegado declarado a partir de un tipo genérico proporcionando argumentos de tipo para sus parámetros de tipo.

Vea también

Tareas

Solucionar problemas de tipos de datos (Visual Basic)

Referencia

Resumen de tipos de datos (Visual Basic)

Of (Cláusula, Visual Basic)

As

Object (Tipo de datos)

Conceptos

Tipos de datos en Visual Basic

Caracteres de tipo (Visual Basic)

Otros recursos

Implementación de tipos de datos (Visual Basic)

Conversiones de tipos en Visual Basic

Covarianza y contravarianza (C# y Visual Basic)