Angella Andrea - Italian Blog

Infinita passione per lo sviluppo software !
posts - 133, comments - 216, trackbacks - 9

My Links

News

MIT OpenCourseWare: I'm invested Wikipedia Affiliate Button


Sto leggendo:

Archives

Post Categories

Siti web realizzati

Siti web tecnici

[70-536] - Delegates


Area di riferimento

- Developing applications that use system types and collections
    - Control interactions between .NET Framework application components by using events and delegates
       - Delegate class


Delegates

Il .NET Framework per implementare il meccanismo delle funzioni di callback utilizza i delegates.

Nei sistemi Windows le funzioni di callback si utilizzano frequentemente per:

  • Ricevere notifiche su eccezioni non gestite
  • Gestire i cambiamenti del file system
  • Gestire gli eventi dei controlli
  • Completare operazioni asincrone
  • ...

La parola chiave delegate permette di definire un tipo che sarà in grado di contenere riferimenti a una o più funzioni che soddisfano una ben precisa firma. Un tipo delegate può essere utilizzato per chiamare metodi statici o metodi di istanza. Nel codice non gestisto C/C++, l'indirizzo di una funzione è semplicemente un indirizzo di memoria. Questo indirizzo non contiene nessuna informazione addizionale come ad esempio il numero, il tipo e l'ordine dei parametri, il tipo del valore di ritorno.

E' possibile vedere i delegate come dei puntatori a funzione con la caratteristica aggiuntiva di essere type-safe e anche in grado di "puntare" a più funzioni.

Vediamo un esempio di codice che crea un delegate, lo istanzia, aggiunge/toglie le funzioni di callback e lo invoca.

// Definisce un delegate in grado di gestire funzioni di callback
// che prendono due interi e restituiscono un intero

public delegate int Funz(int a, int b);

// Particolari funzioni di callback con la stessa firma definita da Funz

public static int somma(int a, int b)
{
    int ris = a + b;
    Console.WriteLine("a + b = {0}", ris);
    return ris;
}

public static int sottrazione(int a, int b)
{
    int ris = a - b;
    Console.WriteLine("a - b = {0}", ris);
    return ris;
}

public static int moltiplicazione(int a, int b)
{
    int ris = a * b;
    Console.WriteLine("a * b = {0}", ris);
    return ris;
}

static void Main(string[] args)
{
    // Costruisco una istanza del delegate e aggiungo le funzioni di callback
    Funz f = somma;    
    f += sottrazione;
    f += moltiplicazione;

    // Invoco le funzioni di callback "puntate" dal delegate
    int ris1 = f(5, 3);
    Console.WriteLine("ris = {0}\n", ris1);   // Output: ris = 15

    // Rimuovo la funzione di moltiplicazione dal delegate
    f -= moltiplicazione;

    // Invoco di nuovo le funzioni di callback "puntate" dal delegate
    int ris2 = f(5, 3);
    Console.WriteLine("ris = {0}", ris2);     // Output: ris = 2

    Console.ReadKey();
}


Notare che quando il delegate contiene i riferimenti di più funzioni, il valore ritornato dalla sua invocazione corrisponde al valore restituito dall'ultima funzione di callback eseguita. Nell'esempio infatti la prima invocazione restituisce il valore dell'operazione di moltiplicazione mentra la seconda restituisce il valore della sottrazione in quanto l'operazione di moltiplicazione è stata rimossa.

E' importante sapere che di fronte alla definizione di un delegate il compilatore costruisce una classe che deriva da System.MulticastDelegate che a sua volta deriva dalla classe astratta System.Delegate.

Come visto nel codice precedente, il compilatore C# fornisce una sintassi semplice (basata sull'uso degli operatori += e -=) per aggiungere e togliere funzioni da una istanza di un delegate.

In realtà il codice precedente poteva essere scritto nel seguente modo meno leggibile:

static void Main(string[] args)
{
    // Costruisco una istanza di un delegate e aggiungo le funzioni di callback
    Funz f = new Funz(somma);
    f = (Funz) Delegate.Combine(f, new Funz(sottrazione));
    f = (Funz) Delegate.Combine(f, new Funz(moltiplicazione));

    // Invoco le funzioni di callback "puntate" dal delegate
    int ris1 = f(5, 3);
    Console.WriteLine("ris = {0}\n", ris1);

    // Rimuovo la funzione di moltiplicazione dal delegate
    f = (Funz)Delegate.Remove(f, new Funz(moltiplicazione));

    // Invoco di nuovo le funzioni di callback "puntate" dal delegate
    int ris2 = f(5, 3);
    Console.WriteLine("ris = {0}", ris2);
    Console.ReadKey();
}


E' possibile anche notare che C# permette di specificare il nome di un metodo di callback senza dover costruire esplicitamente il delegate.

Un'altro vantaggio sintattico che offre il compilatore C# è la possibilità di scrivere il codice che definisce una funzione di callback direttamente in-line cioè è possibile passare come parametro di un metodo un blocco di codice. Sarà compito del compilatore racchiudere questo blocco di codice all'interno di un metodo privato il cui nome non ci interessa. Si parla di Anonymous method.

static void esegui(int a, int b, Funz f)
{
     int ris = f(a, b);
     Console.WriteLine(ris);
}

static void Main(string[] args)
{           
     esegui(3, 5, delegate(int a, int b) { return a + b; } );

        esegui(3, 5, delegate { Console.WriteLine("Ciao"); return 0; } );

     Console.ReadKey();
}

Print | posted on sabato 29 dicembre 2007 20:36 | Filed Under [ Exam 70-536 Application Development Foundation ]

Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET