Gli Eventi in C Sharp

Giorgio Borelli

Spiegazione degli eventi in C#Sia che parliamo di programmazione per Windows Form o Web Form la gestione degli eventi in C# è un'aspetto fondamentale che ogni buon programmatore deve conoscere.

Il meccanismo degli eventi consente di notificare dei messaggi tra gli oggetti della mia applicazione al verificarsi di determinate condizioni. Allo scatenarsi di un evento è possibile gestirlo opportunamente per effettuare operazioni ed intraprendere azioni per variare il comportamento dell'applicazione come reazione al cambiamento del suo stato.

Un oggetto che genera un'evento, lo notifica ad un'altro che lo prende in carico e lo gestisce (handler dell'evento), tale meccanismo viene implementato per mezzo dei delegates, gli eventi in C# non sono altro che particolari tipi di delegate multicast.

Gli eventi allora completano le nostre classi, corredandole oltre che di metodi e proprietà, anche di un meccanismo per la notifica di messaggi agli altri oggetti, con la possibilità anche di gestirli con azioni (gestore dell'evento, handler) che interessano il cambiamento di stato. La classe base del .NET framework dal quale far derivare la definizione delle nostre classi per gli eventi è System.EventArgs, e specificare il delegate che ne rappresenta la firma per il gestore dell'evento (handler). Per i delegate, il tipo base per il gestore degli eventi è System.EventHandler, quest'ultimo accetta due parametri in ingresso, uno di tipo Sender che non è altro che l'oggetto che ha scatenato l'evento, e l'altro di tipo EventArgs ossia l'evento stesso contenente tutte le informazioni su di esso. Mentre per definire un evento come membro di una classe è necessario farlo tramite la parola chiave event. Come vedete la relazione tra eventi e delegati è strettissima.

Gli eventi sono molto usati nella programmazione Windows, Windows stesso si basa su un meccanismo ad eventi, inoltre sia in applicazioni desktop (le Win Form) che in quelle Web (Web Form) lo scatenarsi di un evento è spesso legato all'interazione dell'utente con l'applicazione, il più banale degli esempi è quello della pressione di un bottone che genera l'evento click.

Ogni evento definito all'interno di una classe, possiede uno o più handler (event multicast) per eseguire l'azione necessaria (consumare l'evento) al suo verificarsi, Per sottoscrivere un handler ad un evento si fà uso dell'operatore +=, l'operazione inversa invece di desottoscrizione avviene con l'operatore -=.

Supponiamo di avere un Button con "ID=ButtonSend" per l'invio delle informarzioni di un form, tramite l'IDE di Visual Studio o tramite la colonna Properties del button è facile creare il gestore del corrispondente evento click, ma se volessimo fare tutto a manina dovremmo più o meno scrivere così:

//sottoscrivo l'evento all'Handler generico
ButtonSend.Click += new EventHandler(OnButtonSend_Click);

//gestore dell'evento
protected void OnButtonSend_Click(object sender, EventArgs e)
{
    //do something ...
}

Come notate il gestore dell'evento, per convenzione preceduto da "On", accetta i due parametri Sender ed EventArgs che riconrdiamo sono l'oggetto che ha scatenato l'evento e l'oggetto contenente le informazioni sull'evento (che può essere anche una classe derivante da EventArgs da noi appositamente definita).

 

Gli eventi in C# non vengono usati soltanto per notificare un semplice click di un bottone, ma in moltissimi altri e più complessi casi, come per la realizzazione di servizi windows ed applicazioni multitrhead, la loro importanza è quindi davvero notevole in qualsiasi ramo della programmazione noi vogliamo lanciarci, conoscerli ed assimilarli è pertanto fondamentale per ogni buon sviluppatore.

Categorie: C#

Tags: ,

Commenti (3) -

Grazie dell'illustrazione.
Potresti fare un esempio in cui una classe qualsiasi lancia un evento e un'altra classe, che istanzia l'oggetto della prima classe, resta in ascolto dell'evento e ne implementa la callback?

ad esempio, tanto per dire, la classe Automobile ha la proprietà motore di classe Motore; il motore invia un evento quando viene avviato, e quindi nell'istanza di Automobile vorrei un listener che resti in attesa della ricezione dell'evento "motoreAvviato" da parte di motore.

in tutti gli esempi che trovo online non ho mai trovato un esempio custom ma sempre in riferimento ad un lancio di eventi già presenti nel framework legato ai form.

Grazie.

Rispondi

using System;

public class Motore
{
    public event EventHandler Acceso;

    private string alimentazione;
    private int cilindrata;
    private bool stato;

    public string MotoreAlimentazione
    {
        get { return this.alimentazione; }
        set { this.alimentazione = value; }
    }

    public int MotoreCilindrata
    {
        get { return this.cilindrata; }
        set { this.cilindrata = value; }
    }

    public bool MotoreStato
    {
        get { return this.stato; }
        set
        {
            this.stato = value;
            if (this.Acceso != null)
                this.Acceso(this, new EventArgs());
        }
    }

    /// <summary>
    /// Costruttore
    /// </summary>
    public Motore()
    {
    }
}

Una volta definita la classe Motore, con le sue proprietà e costruttore, poniamo attenzione alla proprietà MotoreStato, all'interno del set controllo che  l'evento Acceso sia nullo o meno, scatenando di conseguenza l'evento oppure no.

Supponiamo adesso di trovarci all'interno del nostro codice:

//instazio l'ogetto
Motore engine = new Motore();

//aggiungo il gestore di evento (handler) per l'evento Acceso dell'oggetto macchina (classe motore)
engine.Acceso += new AccesoEventHandler(engine_Acceso);

//setto la proprietà MotoreStato a true
macchina.MotoreStato = true;
// modificando questa proprietà (entro nel set) scateno l'evento che viene preso in carico dal gestore aggiunto pocanzi "engine_Acceso"
...

//signature della funzione gestore dell'evento
void engine_Acceso(object sender, EventArgs e)
{
    //lo stato del motore è stato modificato
    //qui metterai il tuo codice, hai sender ed e
    //come parametri
}

Questa funzione engine_Acceso viene invocata ogni qual volta cambia lo stato della proprietà MotoreAcceso di Motore (nell'oggetto macchina), puoi definirla dove meglio credi, anche all'interno di una classe ManagerAuto come dicevi nel tuo esempio, attenzione però che il sender (primo parametro) di engine_Acceso è un object ma effettivamente sta ricevendo un boolean, quindi devi fare il cast, oppure per essere proprio precisi ed eleganti nella classe Motore ti definisci tramite i delegate un Event "Acceso" che accetti come sender un bool anzichè un object (per come è adesso), poi il resto è uguale.

Ho semplificato un attimo l'esempio da te proposto per ovvie ragioni di tempo e di spazio, ma credo che riuscirai ad adattarlo perfettamente alle tue esigenze.

Ciao ciao.

Rispondi

ERRATA CORRIGE: dove vedi o mi riferisco all'ogetto "macchina" ovviamente ci và "engine".
Avevo fatto delle modifiche al volo all'esempio e mi sono sfuggite queste correzioni.

Rispondi

Pingbacks and trackbacks (1)+

Aggiungi Commento

biuquote
Loading