Delegados en C#: Guía completa de referencias a funciones y eventos
Los delegados en C# son similares a los punteros a funciones en C o C++. Un delegado es una variable de tipo referencia que contiene la referencia a un método. Esta referencia puede cambiarse en tiempo de ejecución.
Los delegados se utilizan especialmente para implementar eventos y métodos de devolución de llamada (callbacks). Todos los delegados se derivan implícitamente de la clase System.Delegate.
Declaración de delegados
La declaración de un delegado determina qué métodos puede referenciar. Un delegado solo puede referenciar métodos que tengan la misma firma que el delegado.
Por ejemplo, considere el siguiente delegado:
public delegate int MiDelegado(string s);
Este delegado puede referenciar cualquier método que tenga un único parámetro string y devuelva un valor de tipo int.
La sintaxis para la declaración de delegados es:
delegate <tipo de retorno> <nombre-delegado> <lista de parámetros>
Instanciación de delegados
Una vez declarado un tipo de delegado, se debe crear un objeto delegado con la palabra clave new y asociarlo a un método específico. Al crear un delegado, el argumento pasado a la expresión new se escribe de forma similar a una llamada de método, pero sin los argumentos del método. Por ejemplo:
public delegate void ImprimirCadena(string s); ... ImprimirCadena ps1 = new ImprimirCadena(EscribirEnPantalla); ImprimirCadena ps2 = new ImprimirCadena(EscribirEnArchivo);
El siguiente ejemplo demuestra la declaración, instanciación y uso de un delegado que puede referenciar métodos que toman un parámetro entero y devuelven un valor entero.
Demo en vivousing System;
delegate int CambiadorNumero(int n);
namespace AplicacionDelegado {
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 nc1 = new CambiadorNumero(SumarNum);
CambiadorNumero nc2 = new CambiadorNumero(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
Multidifusión (Multicasting) de un delegado
Los objetos delegado se pueden componer usando el operador +. Un delegado compuesto llama a los dos delegados de los que se compuso. Solo se pueden componer delegados del mismo tipo. El operador - se puede usar para eliminar un delegado componente de un delegado compuesto.
Utilizando esta propiedad de los delegados, puede crear una lista de invocación de métodos que se llamarán cuando se invoque un delegado. Esto se denomina multidifusión de un delegado. El siguiente programa demuestra la multidifusión de un delegado:
Demo en vivousing System;
delegate int CambiadorNumero(int n);
namespace AplicacionDelegado {
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 nc;
CambiadorNumero nc1 = new CambiadorNumero(SumarNum);
CambiadorNumero nc2 = new CambiadorNumero(MultiplicarNum);
nc = nc1;
nc += nc2;
// Llamar a la multidifusión
nc(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: 75
Uso de delegados
El siguiente ejemplo demuestra el uso de delegados. El delegado ImprimirCadena puede usarse para referenciar un método que toma una cadena como entrada y no devuelve nada.
Utilizamos este delegado para llamar a dos métodos: el primero imprime la cadena en la consola y el segundo la imprime en un archivo:
Demo en vivousing System;
using System.IO;
namespace AplicacionDelegado {
class ImprimirCadena {
static FileStream fs;
static StreamWriter sw;
// Declaración del delegado
public delegate void ImprimirCadena(string s);
// Este método imprime en la consola
public static void EscribirEnPantalla(string str) {
Console.WriteLine("La cadena es: {0}", str);
}
// Este método imprime en un archivo
public static void EscribirEnArchivo(string s) {
fs = new FileStream("c:\\mensaje.txt", FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs);
sw.WriteLine(s);
sw.Flush();
sw.Close();
fs.Close();
}
// Este método toma el delegado como parámetro y lo usa para
// llamar a los métodos según sea necesario
public static void EnviarCadena(ImprimirCadena ps) {
ps("Hola Mundo");
}
static void Main(string[] args) {
ImprimirCadena ps1 = new ImprimirCadena(EscribirEnPantalla);
ImprimirCadena ps2 = new ImprimirCadena(EscribirEnArchivo);
EnviarCadena(ps1);
EnviarCadena(ps2);
Console.ReadKey();
}
}
}
Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:
La cadena es: Hola Mundo
Lenguaje C
- La IA protagonista en la Cumbre de Innovación de The Economist: Líderes piden aumentar, no reemplazar, las habilidades humanas
- 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#
- Cuatro patrones probados para funciones definidas por el usuario en C
- Cómo pasar arrays 1D y 2D a funciones en C – Guía práctica
- Variables y tipos de datos en C++: Guía experta sobre int, double, char, string, bool
- Dominando funciones en C: Estructura, declaración y mejores prácticas
- Uso eficiente de memoria con campos de bits en C
- Dominando Argumentos Variables en C: Guía Práctica