Para ver el artículo en inglés, active la casilla Inglés. También puede ver el texto en inglés en una ventana emergente si pasa el puntero del mouse por el texto.
Traducción
Inglés

Genéricos en .NET Framework

 

Los genéricos permiten personalizar un método, clase, estructura o interfaz con respecto a los datos precisos sobre los que se actúa. Por ejemplo, en lugar de utilizar la clase Hashtable, que permite cualquier tipo de clave y valor, puede utilizar la clase genérica Dictionary<TKey, TValue> y especificar el tipo permitido para la clave y el tipo permitido para el valor. Entre las ventajas de los genéricos están una mayor reutilización del código y la seguridad de tipos.

En este tema se proporciona información general sobre los genéricos en .NET Framework, así como un resumen de los métodos o tipos genéricos. Contiene las siguientes secciones:

Los genéricos son clases, estructuras, interfaces y métodos que tienen marcadores de posición (parámetros de tipo) para uno o varios de los tipos que almacenan o utilizan. Una clase de colección genérica puede usar un parámetro de tipo como marcador de posición para el tipo de objetos que almacena; los parámetros de tipo aparecen como los tipos de sus campos y los tipos de parámetros de sus métodos. Un método genérico puede usar su parámetro de tipo como el tipo de su valor devuelto o como el tipo de uno de sus parámetros formales. El código siguiente ilustra una definición de clase genérica simple.

public class Generic<T>
{
    public T Field;
}

Cuando cree una instancia de una clase genérica, especifique los tipos reales que hay que sustituir para los parámetros de tipo. Esto establece una nueva clase genérica, a la que se hace referencia como clase genérica construida, con los tipos que elija sustituidos en todas partes en la que aparecen los parámetros de tipo. El resultado es una clase con seguridad de tipos que se adapta a su elección de tipos, como se muestra en el código siguiente.

public static void Main()
{
    Generic<string> g = new Generic<string>();
    g.Field = "A string";
    //...
    Console.WriteLine("Generic.Field           = \"{0}\"", g.Field);
    Console.WriteLine("Generic.Field.GetType() = {0}", g.Field.GetType().FullName);
}

Los siguientes términos se utilizan para explicar los genéricos en el.NET Framework:

  • Una definición de tipo genérico es una clase, estructura o declaración de interfaz que funciona como una plantilla, con marcadores de posición para los tipos que puede contener o utilizar. Por ejemplo, la clase System.Collections.Generic.Dictionary<TKey, TValue> puede contener dos tipos: claves y valores. Dado que una definición de tipo genérico es solo una plantilla, no se pueden crear instancias de una clase, estructura o interfaz que sea una definición de tipo genérico.

  • Los parámetros de tipo genérico, o parámetros de tipo, son los marcadores de posición en una definición de método o tipo genérico. El tipo genérico System.Collections.Generic.Dictionary<TKey, TValue> tiene dos parámetros de tipo, TKey y TValue, que representan los tipos de sus claves y valores.

  • Un tipo genérico construido, o tipo construido, es el resultado de especificar los tipos para los parámetros de tipo genérico de una definición de tipo genérico.

  • Un argumento de tipo genérico es cualquier tipo que se sustituye por un parámetro de tipo genérico.

  • El término general tipo genérico incluye tanto tipos construidos como definiciones de tipo genérico.

  • La covarianza y contravarianza de parámetros de tipo genérico permite usar tipos genéricos construidos, cuyos argumentos de tipo están más derivados (covarianza) o menos derivados (contravarianza) que un tipo construido de destino. La covarianza y la contravarianza se denominan colectivamente varianza. Para obtener más información, consulta Covarianza y contravarianza en genéricos.

  • Las restricciones son límites colocados en parámetros de tipo genérico. Por ejemplo, puede limitar un parámetro de tipo a tipos que implementan la interfaz genérica System.Collections.Generic.IComparer<T> para asegurarse de que se pueden ordenar las instancias del tipo. También puede restringir los parámetros de tipo a tipos que tienen una clase base concreta, un constructor predeterminado o que son tipos de referencia o tipos de valor. Los usuarios del tipo genérico no pueden sustituir los argumentos de tipo que no cumplen con las restricciones.

  • Una definición de método genérico es un método con dos listas de parámetros: una lista de parámetros de tipo genérico y una lista de parámetros formales. Los parámetros de tipo pueden aparecer como el tipo de valor devuelto o como los tipos de los parámetros formales, como se muestra en el siguiente código.

T Generic<T>(T arg)
{
    T temp = arg;
    //...
    return temp;
}

Los métodos genéricos pueden aparecer en tipos genéricos o no genéricos. Es importante tener en cuenta que un método no es genérico solo porque pertenezca a un tipo genérico, ni siquiera porque tenga parámetros formales cuyos tipos sean los parámetros genéricos del tipo envolvente. Un método solo es genérico si tiene su propia lista de parámetros de tipo. En el siguiente código, solo es genérico el método G.

class A
{
    T G<T>(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}
class Generic<T>
{
    T M(T arg)
    {
        T temp = arg;
        //...
        return temp;
    }
}

Volver al principio

Usar delegados y colecciones genéricas ofrece muchas ventajas:

  • Seguridad de tipos. Los genéricos trasladan al compilador la carga de la seguridad de tipos. No es necesario escribir código para comprobar el tipo de datos correcto porque se hace en tiempo de compilación. Se reduce la necesidad de conversión de tipos y la posibilidad de errores en tiempo de ejecución.

  • Menos código que, además, se reutiliza más fácilmente. No es necesario heredar de un tipo base y reemplazar a los miembros. Por ejemplo, LinkedList<T> está listo para su uso inmediato. Por ejemplo, puede crear una lista vinculada de cadenas con la siguiente declaración de variable:

    LinkedList<string> llist = new LinkedList<string>();
    
  • Mejor rendimiento. Los tipos de colección genéricos suelen comportarse mejor en el almacenamiento y manipulación de tipos de valor porque no es necesario realizar una conversión boxing de los tipos de valor.

  • Los delegados genéricos permiten devoluciones de llamada con seguridad de tipos sin necesidad de crear varias clases de delegado. Por ejemplo, el delegado genérico Predicate<T> le permite crear un método que implementa sus propios criterios de búsqueda para un tipo concreto y utilizar su método con métodos del tipo Array, como Find<T>, FindLast<T> y FindAll<T>.

  • Los genéricos optimizan el código generado dinámicamente. Cuando se utilizan genéricos con código generado dinámicamente, no es necesario generar el tipo. Esto aumenta el número de escenarios en los que puede utilizar métodos dinámicos ligeros en lugar de generar ensamblados completos. Para obtener más información, vea el tema sobre cómo definir y ejecutar métodos dinámicos y DynamicMethod.

Las siguientes son algunas limitaciones de los genéricos:

  • Los tipos genéricos pueden derivarse de la mayoría de las clases base, como MarshalByRefObject (y pueden utilizarse restricciones para exigir que los parámetros de tipo genérico se deriven de clases base como MarshalByRefObject). Sin embargo, .NET Framework no es compatible con los tipos genéricos enlazados a un contexto. Un tipo genérico puede derivarse de ContextBoundObject, pero al intentar crear una instancia de dicho tipo, se genera una TypeLoadException.

  • Las enumeraciones no pueden tener parámetros de tipo genérico. Una enumeración solo puede ser genérica a propósito (por ejemplo, porque está anidada en un tipo genérico definido mediante Visual Basic, C# o C++). Para más información, vea "Enumeraciones" en Sistema de tipos comunes.

  • Los métodos dinámicos ligeros no pueden ser genéricos.

  • En Visual Basic, C# y C++, no se pueden crear instancias de un tipo anidado incluido en un tipo genérico, a menos que los tipos se hayan asignado a los parámetros de tipo de todos los tipos envolventes. Dicho de otro modo: en la reflexión, un tipo anidado definido mediante estos lenguajes incluye los parámetros de tipo de todos sus tipos envolventes. Esto permite que los parámetros de tipo de tipos envolventes se usen en las definiciones de miembro de un tipo anidado. Para obtener más información, vea “Tipos anidados” en MakeGenericType.

    System_CAPS_noteNota

    Un tipo anidado definido mediante la emisión de código en un ensamblado dinámico o mediante el uso de Ilasm.exe (IL Assembler) no necesita incluir los parámetros de tipo de sus tipos envolventes; sin embargo, si no los incluye, los parámetros de tipo no estarán en el ámbito de la clase anidada.

    Para obtener más información, vea “Tipos anidados” en MakeGenericType.

Volver al principio

.NET Framework ofrece una serie de clases de colección genérica en los espacios de nombres siguientes:

Las interfaces genéricas para implementar comparaciones de orden e igualdad se proporcionan en el espacio de nombres System, junto con los tipos de delegado genérico para controladores de eventos, conversiones y predicados de búsqueda.

Se ha agregado compatibilidad con genéricos a los siguientes espacios de nombres: a System.Reflection para examinar tipos y métodos genéricos; a System.Reflection.Emit para emitir ensamblados dinámicos que contengan tipos y métodos genéricos; y a System.CodeDom para generar gráficos de origen que incluyan genéricos.

Common language runtime proporciona nuevos opcode y prefijos para admitir tipos genéricos en el lenguaje intermedio de Microsoft (MSIL), incluidos Stelem, Ldelem, Unbox_Any, Constrained y Readonly.

Visual C++, C# y Visual Basic proporcionan compatibilidad completa para definir y utilizar genéricos. Para más información sobre la compatibilidad de lenguajes, vea Tipos genéricos en Visual Basic (Visual Basic), Introducción a los genéricos (Guía de programación de C#) y Información general sobre genéricos en Visual C++.

Volver al principio

Un tipo que está anidado en un tipo genérico puede depender de los parámetros de tipo del tipo genérico envolvente. Common language runtime considera que los tipos anidados son genéricos, aunque no tengan sus propios parámetros de tipo genérico. Cuando cree una instancia de un tipo anidado, especifique los argumentos de tipo para todos los tipos genéricos envolventes.

Volver al principio

Título

Descripción

Colecciones genéricas en .NET Framework

Describe las clases de colección genérica y otros tipos genéricos en .NET Framework.

Delegados genéricos para manipular matrices y listas

Describe los delegados genéricos para conversiones, predicados de búsqueda y acciones realizadas en los elementos de una matriz o colección.

Interfaces genéricas

Describe las interfaces genéricas que proporcionan funcionalidad común entre las familias de tipos genéricos.

Covarianza y contravarianza en genéricos

Describe la covarianza y la contravarianza en los parámetros de tipo genérico.

Tipos de colección utilizados normalmente

Proporciona información de resumen sobre las características y escenarios de uso de los tipos de colección en .NET Framework, incluidos los tipos genéricos.

Cuándo utilizar colecciones genéricas

Describe las reglas generales para determinar cuándo utilizar los tipos de colección genéricos.

How to: Define a Generic Type with Reflection Emit

Explica cómo generar ensamblados dinámicos que incluyan métodos y tipos genéricos.

Tipos genéricos en Visual Basic (Visual Basic)

Describe los genéricos a los usuarios de Visual Basic e incluye temas sobre el uso y la definición de tipos genéricos.

Introducción a los genéricos (Guía de programación de C#)

Proporciona información general sobre la definición y uso de tipos genéricos para usuarios de C#.

Información general sobre genéricos en Visual C++

Describe los genéricos a los usuarios de C++ e incluye las diferencias entre genéricos y plantillas.

Mostrar: