Introducción a C # Generics

Entonces, ¿cuál es el concepto de genéricos en C #? En palabras simples, es el concepto de definir clases independientes de tipo, interfaces, métodos, delegados, propiedades, etc. Esto significa que puede definir una clase genérica o cuerpo de método y proporcionar el tipo real durante la invocación.

Por lo tanto, los genéricos son como plantillas de código. Le permiten escribir un bloque de código de tipo seguro sin hacer referencia a ningún tipo de datos en particular. El tipo de su código se determina en tiempo de compilación durante la llamada de invocación para su clase o método.

Sintaxis de genéricos en C #

Veamos la sintaxis de una declaración genérica en C #. Es una sintaxis muy simple.

Como práctica común, la letra 'T', en mayúscula y entre corchetes angulares, denota la declaración de un código genérico en C #. Pero, este no es el mandato. Cualquier letra en mayúscula entre corchetes angulares se puede usar para denotar un código genérico.

Declarando una clase genérica:

public class MyGenericClass

Instanciar una clase genérica:

MyGenericClass = new MyGenericClass();

Declarando una clase derivada genérica:

public class MyGenericDerivedClass : MyGenericBaseClass

Declarando un método genérico:

public T MyGenericMethod(T item);

¿Cómo funcionan los genéricos en C #?

Cuando declara un código genérico en C #, el compilador produce una plantilla equivalente a ese código. Esta plantilla se verifica para todos los errores de compilación, excepto la seguridad de tipos. El siguiente paso se produce cuando se invoca o se invoca el código genérico en otra parte del programa. En el momento de la invocación, especifique el tipo con el que se compilaría su código genérico. Cuando el compilador alcanza el punto de invocación, inserta el tipo especificado en la plantilla compilada previamente. Esto se vuelve a compilar para verificar la seguridad de tipo. Una vez aprobado, el código está listo para su ejecución.

Veríamos el código compilado en los ejemplos a continuación para comprender mejor las plantillas genéricas.

Ejemplo de genéricos en C #

A continuación se muestran los diferentes ejemplos de genéricos de C #:

Genéricos con clase

Código:

using System;
using System.Collections.Generic;
public class GenericClass
(
List genericList;
public GenericClass()
(
genericList = new List();
)
public void AddToList(T item)
(
genericList.Add(item);
)
public void DisplayList()
(
foreach (var ele in genericList)
(
Console.Write("(0)\t", ele);
)
)
)
public class Program
(
public static void Main()
(
GenericClass intGenericObj = new GenericClass();
GenericClass stringGenericObj = new GenericClass();
intGenericObj.AddToList(28);
intGenericObj.AddToList(999);
intGenericObj.AddToList(0);
intGenericObj.AddToList(-123);
intGenericObj.AddToList(100);
stringGenericObj.AddToList("Hello");
stringGenericObj.AddToList("Bonjour");
stringGenericObj.AddToList("Ola");
stringGenericObj.AddToList("Ciao");
stringGenericObj.AddToList("Hallo");
intGenericObj.DisplayList();
Console.WriteLine("\n");
stringGenericObj.DisplayList();
))

Salida:

El mismo código también se puede volver a escribir como a continuación. Esto ilustra el poder de definir una clase genérica que se puede hacer de tipo seguro para múltiples tipos en un solo objeto.

using System;
using System.Collections.Generic;
public class GenericClass
(
List genericList1;
List genericList2;
public GenericClass()
(
genericList1 = new List();
genericList2 = new List();
)
public void AddToList(T item1, U item2)
(
genericList1.Add(item1);
genericList2.Add(item2);
)
public void DisplayList()
(
foreach (var ele in this.genericList1)
(
Console.Write("(0)\t", ele);
)
Console.WriteLine("\n");
foreach (var ele in this.genericList2)
(
Console.Write("(0)\t", ele);
)
)
)
public class Program
(
public static void Main()
(
GenericClass genericObj = new GenericClass();
genericObj.AddToList(28, "Hello");
genericObj.AddToList(999, "Bonjour");
genericObj.AddToList(0, "Ola");
genericObj.AddToList(-123, "Ciao");
genericObj.AddToList(100, "Hallo");
genericObj.DisplayList();
)
)

Salida:

Código compilado:

Para obtener una perspectiva de cómo se resuelve el tipo de datos en genéricos, veamos el código compilado generado cuando instanciamos la clase con tipos enteros y de cadena en el ejemplo anterior.

using System;
using System.Collections.Generic;
public class GenericClass
(
List genericList1;
List genericList2;
public GenericClass()
(
genericList1 = new List();
genericList2 = new List();
)
public void AddToList(int item1, string item2)
(
genericList1.Add(item1);
genericList2.Add(item2);
)
public void DisplayList()
(
foreach (var ele in this.genericList1)
(
Console.Write("(0)\t", ele);
)
Console.WriteLine("\n");
foreach (var ele in this.genericList2)
(
Console.Write("(0)\t", ele);
)
)
)
public class Program
(
public static void Main()
(
GenericClass genericObj = new GenericClass();
genericObj.AddToList(28, "Hello");
genericObj.AddToList(999, "Bonjour");
genericObj.AddToList(0, "Ola");
genericObj.AddToList(-123, "Ciao");
genericObj.AddToList(100, "Hallo");
genericObj.DisplayList();
)
)

Genéricos con método

Código:

using System;
using System.Collections.Generic;
public class Program
(
public static void Main()
(
int() intArr = (12, 23, 43, 94, 35);
double() doubleArr = (12.3, 45.6, 98.7, 1.45, 82.653);
string() strArr = ("Hello", "Bonjour", "Ola", "Ciao", "Hallo");
Console.WriteLine("The largest integer in the array is (0)", findMax(intArr));
Console.WriteLine("The largest floating-point number in the array is (0)", findMax(doubleArr));
Console.WriteLine("The largest string in the array is (0)", findMax(strArr));
)
static T findMax(T() items)
where T : IComparable
(
T max = items(0);
int position = 0;
for (int i = 1; i < items.Length; i++)
(
if (items(i).CompareTo(max) > 0)
(
max = items(i);
position = i;
)
)
return max;
)
)

Salida:

El espacio de nombres System.Collections.Generic

El espacio de nombres System.Collections.Generic en C # contiene interfaces y clases que definen las colecciones genéricas. Permiten a los programadores crear colecciones genéricas que tienen un mejor rendimiento y tipos tan fuertes como las colecciones no genéricas.

Este espacio de nombres contiene listas, diccionarios, listas enlazadas, hashes, pares clave-valor, pilas, etc., todos los cuales son de naturaleza genérica. Los programadores pueden implementarlos en su código.

Importancia de los genéricos de C #

A continuación se muestra la importancia de C # Generics de la siguiente manera:

  • Los genéricos permiten la reutilización de código: el principio fundamental de una buena programación. No necesita escribir el mismo código para cada tipo de datos esperado. Simplemente defina un código independiente del tipo y dígale al compilador que el tipo de datos real se proporcionará en el momento de la invocación del código.
  • Evite el costo del boxeo y el desempaquetado: por supuesto, el uso de genéricos se puede omitir a través de la clase de objeto. Los dos códigos de abajo son equivalentes en sus tareas.

Código genérico: public T MyFunc (elemento T);

Código no genérico: objeto público MyFunc (elemento de objeto)

La clase de objeto reemplaza a todas las clases y, por lo tanto, el código no genérico anterior también se puede utilizar para generar plantillas de código independientes del tipo.

Pero, hay una gran brecha de rendimiento entre los dos códigos. El uso de la clase de objeto conlleva un costo adicional de boxeo y unboxing de los tipos de datos. Los genéricos eliminan esto y, por lo tanto, tienen un mejor rendimiento.

Conclusión

Por lo tanto, hemos visto cómo los genéricos son una característica de programación imprescindible. Este es un concepto muy útil, no solo en C # sino en la mayoría de los lenguajes de programación modernos.

Además, se recomienda conocer el espacio de nombres System.Collections.Generic en C #. Además, para comprender el rendimiento de los genéricos, profundice en cómo el boxeo y el desempaque tienen un impacto en la memoria y en el tiempo de ejecución.

Artículos recomendados

Esta es una guía de C # Generics. Aquí discutimos la importancia y cómo funcionan los genéricos en C # junto con diferentes ejemplos e implementación de código. También puede consultar nuestros otros artículos sugeridos para obtener más información:

  1. Comparación cabeza a cabeza de C # u operador
  2. Sobrecarga y anulación en Java
  3. ¿Cuál es el uso de la sobrecarga de métodos?
  4. ¿Cómo funciona Sealed Class en C #?
  5. Tipos y errores de manejo en JavaScript
  6. Colecciones PL / SQL | Sintaxis, Tipos, Excepciones