C # - Delegati

I delegati C # sono simili ai puntatori alle funzioni, in C o C ++. UNdelegateè una variabile del tipo di riferimento che contiene il riferimento a un metodo. Il riferimento può essere modificato in fase di esecuzione.

I delegati sono usati specialmente per implementare eventi e metodi di callback. Tutti i delegati derivano implicitamente daSystem.Delegate classe.

Dichiarazione dei delegati

La dichiarazione del delegato determina i metodi a cui può fare riferimento il delegato. Un delegato può fare riferimento a un metodo che ha la stessa firma di quella del delegato.

Ad esempio, considera un delegato:

public delegate int MyDelegate (string s);

Il delegato precedente può essere utilizzato per fare riferimento a qualsiasi metodo che abbia un singolo parametro di stringa e restituisca una variabile di tipo int .

La sintassi per la dichiarazione del delegato è:

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

Creazione di istanze dei delegati

Dopo aver dichiarato un tipo di delegato, è necessario creare un oggetto delegato con l'estensione new parola chiave ed essere associato a un metodo particolare. Durante la creazione di un delegato, l'argomento è passato anewl'espressione viene scritta in modo simile a una chiamata al metodo, ma senza gli argomenti del metodo. Ad esempio:

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

L'esempio seguente dimostra la dichiarazione, la creazione di istanze e l'uso di un delegato che può essere usato per fare riferimento a metodi che accettano un parametro intero e restituisce un valore intero.

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();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Value of Num: 35
Value of Num: 175

Multicasting di un delegato

Gli oggetti delegato possono essere composti utilizzando l'operatore "+". Un delegato composto chiama i due delegati da cui è stato composto. È possibile comporre solo delegati dello stesso tipo. L'operatore "-" può essere utilizzato per rimuovere un delegato componente da un delegato composto.

Utilizzando questa proprietà dei delegati è possibile creare un elenco di chiamate di metodi che verranno chiamati quando viene richiamato un delegato. Questo è chiamatomulticastingdi un delegato. Il seguente programma dimostra il multicasting di un delegato:

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();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

Value of Num: 75

Utilizzo dei delegati

L'esempio seguente mostra l'uso di delegate. Il delegato printString può essere utilizzato per fare riferimento a un metodo che accetta una stringa come input e non restituisce nulla.

Usiamo questo delegato per chiamare due metodi, il primo stampa la stringa sulla console e il secondo la stampa su un file -

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();
      }
   }
}

Quando il codice precedente viene compilato ed eseguito, produce il seguente risultato:

The String is: Hello World