Genéricos en C# explicados: Código flexible y seguro para cualquier tipo de dato
Los genéricos permiten definir la especificación del tipo de dato de elementos de programación en una clase o método hasta que se usa realmente en el programa. En otras palabras, los genéricos permiten escribir una clase o método que funcione con cualquier tipo de dato.
Escribe las especificaciones para la clase o método con parámetros sustitutos para los tipos de dato. Cuando el compilador encuentra un constructor para la clase o una llamada a función para el método, genera código para manejar el tipo de dato específico. Un ejemplo simple ayudará a entender el concepto:
Demo en vivousing System;
using System.Collections.Generic;
namespace AplicacionGenerica {
public class MiArrayGenerico<T> {
private T[] array;
public MiArrayGenerico(int tamaño) {
array = new T[tamaño + 1];
}
public T ObtenerElemento(int índice) {
return array[índice];
}
public void EstablecerElemento(int índice, T valor) {
array[índice] = valor;
}
}
class Probador {
static void Main(string[] args) {
// Declarar un array de int
MiArrayGenerico<int> arrayInt = new MiArrayGenerico<int>(5);
// Establecer valores
for (int c = 0; c < 5; c++) {
arrayInt.EstablecerElemento(c, c * 5);
}
// Recuperar valores
for (int c = 0; c < 5; c++) {
Console.Write(arrayInt.ObtenerElemento(c) + " ");
}
Console.WriteLine();
// Declarar un array de char
MiArrayGenerico<char> arrayChar = new MiArrayGenerico<char>(5);
// Establecer valores
for (int c = 0; c < 5; c++) {
arrayChar.EstablecerElemento(c, (char)(c + 97));
}
// Recuperar valores
for (int c = 0; c < 5; c++) {
Console.Write(arrayChar.ObtenerElemento(c) + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
0 5 10 15 20 a b c d e
Características de los genéricos
Los genéricos enriquecen tus programas de las siguientes maneras:
Ayudan a maximizar la reutilización de código, la seguridad de tipos y el rendimiento.
Permiten crear clases de colección genéricas. La biblioteca de clases de .NET Framework contiene varias clases de colección genéricas nuevas en el espacio de nombres System.Collections.Generic.
Permiten crear tus propias interfaces, clases, métodos, eventos y delegados genéricos.
Pueden crear clases genéricas con restricciones para habilitar el acceso a métodos en tipos de dato específicos.
Permiten obtener información sobre los tipos usados en un tipo de dato genérico en tiempo de ejecución mediante reflexión.
Métodos genéricos
En el ejemplo anterior usamos una clase genérica; también podemos declarar un método genérico con un parámetro de tipo. El siguiente programa ilustra el concepto:
Demo en vivousing System;
using System.Collections.Generic;
namespace AplicacionMetodoGenerico {
class Programa {
static void Intercambiar<T>(ref T izq, ref T der) {
T temp;
temp = izq;
izq = der;
der = temp;
}
static void Main(string[] args) {
int a, b;
char c, d;
a = 10; b = 20;
c = 'I'; d = 'V';
// Valores antes del intercambio
Console.WriteLine("Valores enteros antes de intercambiar:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Valores char antes de intercambiar:");
Console.WriteLine("c = {0}, d = {1}", c, d);
// Llamar a intercambiar
Intercambiar<int>(ref a, ref b);
Intercambiar<char>(ref c, ref d);
// Valores después del intercambio
Console.WriteLine("Valores enteros después de intercambiar:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Valores char después de intercambiar:");
Console.WriteLine("c = {0}, d = {1}", c, d);
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
Valores enteros antes de intercambiar: a = 10, b = 20 Valores char antes de intercambiar: c = I, d = V Valores enteros después de intercambiar: a = 20, b = 10 Valores char después de intercambiar: c = V, d = I
Delegados genéricos
Puedes definir un delegado genérico con parámetros de tipo. Por ejemplo:
delegate T CambiadorNumero<T>(T n);
El siguiente ejemplo muestra el uso de este delegado:
Demo en vivousing System;
using System.Collections.Generic;
delegate T CambiadorNumero<T>(T n);
namespace AplicacionDelegadoGenerico {
class PruebaDelegado {
static int num = 10;
public static int SumarNum(int p) {
num += p; return num;
}
public static int MultiplicarNum(int q) {
num *= q; return num;
}
public static int ObtenerNum() {
return num;
}
static void Main(string[] args) {
// Crear instancias de delegado
CambiadorNumero<int> nc1 = new CambiadorNumero<int>(SumarNum);
CambiadorNumero<int> nc2 = new CambiadorNumero<int>(MultiplicarNum);
// Llamar a los métodos usando los objetos delegado
nc1(25);
Console.WriteLine("Valor de Num: {0}", ObtenerNum());
nc2(5);
Console.WriteLine("Valor de Num: {0}", ObtenerNum());
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
Valor de Num: 35 Valor de Num: 175
Lenguaje C
- C# Hola Mundo – Construyendo su primera aplicación en C#
- Entendiendo palabras clave e identificadores en C#: Reglas, listas y mejores prácticas
- Domine variables y tipos de datos primitivos en C#: Guía completa
- Operadores en C# – Guía completa de operadores en C#
- Dominando operadores bit a bit y de desplazamiento en C#: Guía completa
- Fundamentos de C#: Entrada y salida esenciales
- Expresiones, sentencias y bloques en C#: Guía completa con ejemplos prácticos
- Dominando los comentarios en C#: Tipos, mejores prácticas y documentación XML
- Dominando la sentencia switch en C#: Sintaxis, ejemplos y mejores prácticas
- Operador ternario en C#: Guía concisa para expresiones condicionales
- Sentencia break en C#: Cómo y cuándo usarla