93 - Delegados |
Otro concepto que incorpora el lenguaje C# son los delegados que son necesarios en conceptos muy utilizados en C# moderno como son las lambdas y LINQ.
Un delegado almacena la referencia de un método con una estructura definida (en cuanto al tipo de dato que devuelve y los tipos y cantidad de parámetros)
Un ejemplo de sintaxis para declarar un delegado:
delegate void delegadoA(int x, int y);
Un delegado comienza con la palabra clave delegate. Luego se declara la firma del método (tipo de dato que retorna, los parámetros y el nombre del delegado)
Declarar un delegado que reciba dos enteros y retorne un entero.
Plantear una clase Operacion y los métodos que permitan sumar y restar dos enteros.
Llamar a los métodos mediante la definición de un delegado.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Delegados1 { delegate int Operar(int x1, int x2); class Program { public int Sumar(int x, int y) { return x + y; } public int Restar(int x, int y) { return x - y; } static void Main(string[] args) { Program p = new Program(); Console.WriteLine("Suma y resta de dos valores llamando directamente a los métodos."); Console.WriteLine(p.Sumar(10, 5)); Console.WriteLine(p.Restar(10, 5)); Operar delegado = p.Sumar; Console.WriteLine("Suma y resta de dos valores llamando a los métodos a través de delegados"); Console.WriteLine(delegado(10, 5)); delegado = p.Restar; Console.WriteLine(delegado(10, 5)); Console.ReadKey(); } } }
Declaramos el delegado Operar que recibe dos parámetros de tipo int y retorna un int:
delegate int Operar(int x1, int x2);
En la clase Program definimos dos métodos Sumar y Restar que tienen una firma idéntica al delegado Operar:
class Program { public int Sumar(int x, int y) { return x + y; } public int Restar(int x, int y) { return x - y; }
En el método Main definimos un objeto de la clase Program y llamamos directamente sus dos métodos:
static void Main(string[] args) { Program p = new Program(); Console.WriteLine("Suma y resta de dos valores llamando directamente a los métodos."); Console.WriteLine(p.Sumar(10, 5)); Console.WriteLine(p.Restar(10, 5));
Lo nuevo aparece cuando definimos un objeto del tipo delegado Operar y le cargamos la referencia del método Sumar:
Operar delegado = p.Sumar;
La variable delegado tiene ahora la referencia del método Sumar y podemos llamar a dicho método a través del delegado:
Console.WriteLine(delegado(10, 5));
Luego modificamos la variable delegado y almacenamos la referencia al método Restar y llamamos a dicho método a través del delegado:
delegado = p.Restar; Console.WriteLine(delegado(10, 5));
En este problema no tiene ninguna ventaja definir un delegado y llamar a los métodos Sumar y Restar a través de delegados. Hemos presentado este problema con el objetivo de comenzar a entender la sintaxis de como se declara un delegado y que almacena una variable de este tipo. A medida que avancemos veremos las ventajas de delegados cuando definamos lambdas y entremos al tema de LINQ.
Un método puede recibir como parámetro un delegado y a partir de esto llamar al método que almacena el delegado.
Declarar un delegado que reciba dos enteros y retorne un entero.
Plantear una clase Operacion y los métodos que permitan sumar y restar dos enteros. Un tercer método que reciba un delegado y dos enteros.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Delegados2 { delegate int Operar(int x1, int x2); class Program { public int Sumar(int x, int y) { return x + y; } public int Restar(int x, int y) { return x - y; } public void operacion(Operar d, int x, int y) { Console.WriteLine(d(10, 5)); } static void Main(string[] args) { Program p = new Program(); Console.WriteLine("Suma y resta de 10 y 5."); p.operacion(p.Sumar, 10, 5); p.operacion(p.Restar, 10, 5); Console.ReadKey(); } } }
Declaramos el delegado:
delegate int Operar(int x1, int x2);
Declaramos la clase Program y los dos métodos que suman y restan dos enteros:
class Program { public int Sumar(int x, int y) { return x + y; } public int Restar(int x, int y) { return x - y; }
Lo nuevo aparece en el método operacion que recibe en el primer parámetro un delegado de tipo Operar y dos enteros. Dentro del algoritmo del método se llama al método que almacena el delegado:
public void operacion(Operar d, int x, int y) { Console.WriteLine(d(10, 5)); }
En la función Main luego de crear un objeto de la clase Program procedemos a llamar solo al método operacion y pasar en el primer parámetro la referencia del método Sumar o Restar según la actividad que necesitamos hacer con los dos enteros restantes:
static void Main(string[] args) { Program p = new Program(); Console.WriteLine("Suma y resta de 10 y 5."); p.operacion(p.Sumar, 10, 5); p.operacion(p.Restar, 10, 5); Console.ReadKey(); }