C # - Delegados

Los delegados de C # son similares a los punteros a funciones, en C o C ++. UNAdelegatees una variable de tipo de referencia que contiene la referencia a un método. La referencia se puede cambiar en tiempo de ejecución.

Los delegados se utilizan especialmente para implementar eventos y los métodos de devolución de llamada. Todos los delegados se derivan implícitamente de laSystem.Delegate clase.

Declarando delegados

La declaración de delegado determina los métodos a los que puede hacer referencia el delegado. Un delegado puede referirse a un método que tiene la misma firma que la del delegado.

Por ejemplo, considere un delegado:

public delegate int MyDelegate (string s);

El delegado anterior se puede utilizar para hacer referencia a cualquier método que tenga un único parámetro de cadena y devuelva una variable de tipo int .

La sintaxis para la declaración de delegado es -

delegate <return type> <delegate-name> <parameter list>

Creación de instancias de delegados

Una vez que se declara un tipo de delegado, se debe crear un objeto delegado con el new palabra clave y estar asociado con un método en particular. Al crear un delegado, el argumento pasado alnewLa expresión se escribe de forma similar a una llamada a un método, pero sin los argumentos del método. Por ejemplo

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

El siguiente ejemplo demuestra la declaración, la creación de instancias y el uso de un delegado que se puede usar para hacer referencia a métodos que toman un parámetro entero y devuelven un valor entero.

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {
   
   class TestDelegate {
      static int num = 10;
      
      public static int AddNum(int p) {
         num += p;
         return num;
      }
      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
         //create delegate instances
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         
         //calling the methods using the delegate objects
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

Value of Num: 35
Value of Num: 175

Multidifusión de un delegado

Los objetos delegados se pueden componer utilizando el operador "+". Un delegado compuesto llama a los dos delegados de los que estaba compuesto. Solo se pueden componer delegados del mismo tipo. El operador "-" se puede utilizar para eliminar un delegado de componente de un delegado compuesto.

Con esta propiedad de delegados, puede crear una lista de invocación de métodos que se llamarán cuando se invoca a un delegado. Se llamamulticastingde un delegado. El siguiente programa demuestra la multidifusión de un delegado:

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl {
   class TestDelegate {
      static int num = 10;
      
      public static int AddNum(int p) {
         num += p;
         return num;
      }
      public static int MultNum(int q) {
         num *= q;
         return num;
      }
      public static int getNum() {
         return num;
      }
      static void Main(string[] args) {
         //create delegate instances
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         
         nc = nc1;
         nc += nc2;
         
         //calling multicast
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

Value of Num: 75

Usar delegados

El siguiente ejemplo demuestra el uso de delegate. El printString delegado se puede usar para hacer referencia al método que toma una cadena como entrada y no devuelve nada.

Usamos este delegado para llamar a dos métodos, el primero imprime la cadena en la consola y el segundo la imprime en un archivo:

using System;
using System.IO;

namespace DelegateAppl {

   class PrintString {
      static FileStream fs;
      static StreamWriter sw;
      
      // delegate declaration
      public delegate void printString(string s);

      // this method prints to the console
      public static void WriteToScreen(string str) {
         Console.WriteLine("The String is: {0}", str);
      }
      
      //this method prints to a file
      public static void WriteToFile(string s) {
         fs = new FileStream("c:\\message.txt",
         FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
         sw.WriteLine(s);
         sw.Flush();
         sw.Close();
         fs.Close();
      }
      
      // this method takes the delegate as parameter and uses it to
      // call the methods as required
      public static void sendString(printString ps) {
         ps("Hello World");
      }
      
      static void Main(string[] args) {
         printString ps1 = new printString(WriteToScreen);
         printString ps2 = new printString(WriteToFile);
         sendString(ps1);
         sendString(ps2);
         Console.ReadKey();
      }
   }
}

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The String is: Hello World