Delegati ed Eventi in C#

In questa lezione del corso sul linguaggio C#, prenderemo in considerazione un argomento molto complicato, a mio modo di vedere, che consente alle applicazioni di gestire gli eventi, si tratta dei delegati. In applicazioni visuali, tramite il Visual Studio è semplice gestire gli eventi, perché è tutto automatico, ma per meglio capire il funzionamento proviamo a spiegare nel più semplice modo possibile i delegati e gli eventi. I delegati esistono indipendentemente dagli eventi ( pressione di un tasto, scelta di un valore da una lista, ecc.. ecc..) e sebbene i due concetti siano strettamente legati, è possibile utilizzare i delegati semplicemente per disaccoppiare il codice applicativo, demandando funzionalità specifiche all’esterno di una determinata classe. Si può pensare ai delegati come ad una versione più fine delle interfacce, infatti è possibile implementare anche solo un metodo alla volta e sono dei veri e propri oggetti che incapsulano uno specifico metodo finalizzato a rispondere ad una funzione specifica e circoscritta.
I delegati sono dichiarati tramite la parola chiave delegate e come dice la parola stessa vengono delegati per altri metodi, che possono appartenere a più classi, sono simili ai puntatori a funzione del C++, anche se indipendenti dai tipi e sono protetti. Vediamo questo esempio nel quale una funzione viene delegata:

using System;

namespace BaseApp
{
 public delegate double Delegato(double dVal);

 class Program
 {
  static void Main(string[] args)
  {
    Program pr = new Program();
    Delegato q = new Delegato(pr.Quadrato);

    double dVal = 2.5;
    dVal = q(dVal);

    Console.WriteLine("Il valore è {0}", dVal);
    Console.ReadKey();
  }

  public double Quadrato(double dVal)
  {
    return dVal * dVal;
  }
 }
}

come si vede da questo semplice esempio, il metodo Quadrato della classe Program viene delegato con il nome Delegato. Una peculiarità dei delegati è che possono essere sommati o sotratti, vediamone un esempio:

using System;
namespace BaseApp
{
 public delegate double Delegato(double dVal);

 class Program
 {
   static void Main(string[] args)
   {
     Program pr = new Program();
     Delegato q = new Delegato(pr.Quadrato);
     q += new Delegato(pr.Cubo);

     double dVal = 2.5;
     dVal = q(dVal);

     Console.WriteLine("\n\nDelego il Quadrato \
         ed il Cubo con una somma");
     Console.ReadKey();
   }

   public double Quadrato(double dVal)
   {
     Console.WriteLine("Il valore del \
         prodotto tra {0} e {0} è {1}",
           dVal, dVal * dVal);
     return dVal * dVal;
   }

   public double Cubo(double dVal)
   {
     Console.WriteLine("Il valore del prodotto tra \
          {0} e {0} e {0} è {1}",
          dVal, dVal * dVal * dVal);
     return dVal * dVal * dVal;
   }
  }
}

come si può vedere ho sommato due delegati di funzioni, che ricordo devono avere stessa struttura come le interfacce ( stesso tipo di valore di ritorno e stesso tipo di argomenti ). Spero che con questi due esempi abbiate potuto capire i delegati, ho cercato di semplificare al massimo queste nozioni.
L’evento tipo a cui siamo abituati pensare è, per esempio, la pressione di un pulsante nell’interfaccia utente, qui un evento viene generato dal sottosistema a finestre che invia una notifica al gestore ( handler ) relativo. In generale si può pensare ad un evento come ad un cambio dello stato interno di un oggetto, vediamo come implementarlo:

public class GeneraEventi
{
   public delegate void Delegato(object from,
      ArgomentiEvento args);
   public event Delegato mioEvento;
   public void GeneraEvento(ArgomentiEvento args)
   {
        mioEvento(this, args);
   }
}

una classe che intenda gestire gli eventi della classe GeneraEventi può sottoscrivere il proprio metodo di gestione con il seguente codice:

GeneraEventi gi;
....
gi += new GeneraEventi.Delegato( GestoreEventi );

In pratica la parola chiave event consente di applicare solo somme e sottrazioni ai delegati ( delegati multicast ) e mai uguaglianze, questo ovviamente per evitare di cancellare con una chiamata tutti i gestori eventi definiti prima. Se aveste dei dubbi o incertezze potete usufruire del forum sulla programmazione in C#. Nella prossima lezione vedremo di concludere l’esempio sulle WinForms con l’inserimento dei delegati ed eventi per gestire la scelta di un valore dall’elenco a discesa.

<< Lezione PrecedenteInizio CorsoIndice LezioniLezione Successiva >>

Di Giampaolo Rossi

Sviluppatore software da oltre 16 anni.

6 commenti

  1. Ottima guida base.
    Ti consiglierei di inserire anche le stampe che vengono prodotte dal codice.

    1. Grazie, è una lezione del corso su C# e quindi è basilare, l’output prodotto dal codice non voglio ci sia perché i miei lettori e spero studenti devono implementarlo e poi vedere il risultato.

  2. Non credo di aver ben capito il concetto di delegate, in quanto non riesco bene ad immaginarmi dove possa essere applicato.
    Esempi simili a quelli presenti sopra sono presenti anche sul libro Introducing to Visual C# dell’apress, ma anche con quelli, stesso problema.
    io creo un delegato e ad esso vengono delegate le funzionalità di un altro metodo?
    Dovrebbe funzionare così, mi chiedo allora dove posso applicare questo concetto.

    grazie

    1. [io creo un delegato e ad esso vengono delegate le funzionalità di un altro metodo?]

      Le funzionalità di un altro o altri metodi, visto che i delegati si possono sommare e servono per la gestione degli eventi, quindi nelle applicazioni con form per gestire il da farsi quando ad esempio un utente fa clic su un pulsante o apre una casella a discesa o altro…

    1. Ma è il C# che utilizza i delegates ( puntatori a funzione ) per gestire gli eventi. Una volta che sai cosa fanno li puoi utilizzare quando ne hai bisogno, a me personalmente servono solo per gestire gli eventi, ma dagli esempi sopra ( che credo semplici ) puoi valutare quando utilizzarli.

I commenti sono chiusi.