Compartir a través de


Introducción a los tipos genéricos

Los desarrolladores usan genéricos todo el tiempo en .NET, ya sea implícita o explícitamente. Al usar LINQ en .NET, ¿alguna vez observó que estaba trabajando con IEnumerable<T>? O si alguna vez ha visto un ejemplo en línea de un "repositorio genérico" para comunicarse con bases de datos mediante Entity Framework, ¿ha visto que la mayoría de los métodos devuelven IQueryable<T>? Es posible que se haya preguntado cuál es el T en estos ejemplos y por qué está ahí.

Introducidos por primera vez en .NET Framework 2.0, los genéricos son básicamente una "plantilla de código" que permite a los desarrolladores definir estructuras de datos seguras en cuanto al tipo sin comprometerse con un tipo de datos real. Por ejemplo, List<T> es una colección genérica que se puede declarar y usar con cualquier tipo, como List<int>, List<string>o List<Person>.

Para comprender por qué los genéricos son útiles, echemos un vistazo a una clase específica antes y después de agregar genéricos: ArrayList. En .NET Framework 1.0, los ArrayList elementos eran de tipo Object. Cualquier elemento agregado a la colección se convirtió silenciosamente en un Object. Lo mismo ocurriría al leer elementos de la lista. Este proceso se conoce como conversión boxing y unboxing, y afecta al rendimiento. Sin embargo, aparte del rendimiento, no hay ninguna manera de determinar el tipo de datos de la lista en tiempo de compilación, lo que hace que haya código frágil. Los genéricos resuelven este problema definiendo el tipo de datos que contendrá cada instancia de lista. Por ejemplo, solo puede agregar enteros a List<int> y solo agregar Personas a List<Person>.

Los genéricos también están disponibles en tiempo de ejecución. El tiempo de ejecución sabe qué tipo de estructura de datos usa y puede almacenarla en memoria de forma más eficaz.

El ejemplo siguiente es un programa pequeño que ilustra la eficacia de conocer el tipo de estructura de datos en tiempo de ejecución:

  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;

  namespace GenericsExample {
    class Program {
      static void Main(string[] args) {
        //generic list
        List<int> ListGeneric = new List<int> { 5, 9, 1, 4 };
        //non-generic list
        ArrayList ListNonGeneric = new ArrayList { 5, 9, 1, 4 };
        // timer for generic list sort
        Stopwatch s = Stopwatch.StartNew();
        ListGeneric.Sort();
        s.Stop();
        Console.WriteLine($"Generic Sort: {ListGeneric}  \n Time taken: {s.Elapsed.TotalMilliseconds}ms");

        //timer for non-generic list sort
        Stopwatch s2 = Stopwatch.StartNew();
        ListNonGeneric.Sort();
        s2.Stop();
        Console.WriteLine($"Non-Generic Sort: {ListNonGeneric}  \n Time taken: {s2.Elapsed.TotalMilliseconds}ms");
        Console.ReadLine();
      }
    }
  }

Este programa genera una salida similar a la siguiente:

Generic Sort: System.Collections.Generic.List`1[System.Int32]
 Time taken: 0.0034ms
Non-Generic Sort: System.Collections.ArrayList
 Time taken: 0.2592ms

Lo primero que puede observar aquí es que ordenar la lista genérica es significativamente más rápido que ordenar la lista no genérica. También puede observar que el tipo de la lista genérica es distinto ([System.Int32]), mientras que el tipo de la lista no genérica se generaliza. Dado que el tiempo de ejecución sabe que el genérico List<int> es de tipo Int32, puede almacenar los elementos de lista en una matriz de enteros subyacente en la memoria, mientras que el no genérico ArrayList tiene que convertir cada elemento de lista en un objeto. Como se muestra en este ejemplo, las conversiones adicionales consumen tiempo y ralentizan la ordenación de la lista.

Otra ventaja adicional de que el tiempo de ejecución conozca el tipo de la clase genérica es una mejor experiencia de depuración. Cuando se depura un genérico en C#, sabe qué tipo de cada elemento se encuentra en la estructura de datos. Sin genéricos, no tendría idea de qué tipo era cada elemento.

Consulte también