Spiega i delegati di .NET

Quindi leggo MSDN e Stack Overflow. Capisco cosa fa l’Action Delegate in generale, ma non è fare clic non importa quanti esempi faccio. In generale, lo stesso vale per l’idea dei delegati. Quindi questa è la mia domanda. Quando hai una funzione come questa:

public GetCustomers(Action<IEnumerable,Exception> callBack) { } 

Cos’è questo e cosa dovrei passare ad esso?

si aspetta una funzione che accetta IEnumerable e Exception e restituisce void.

 void SendExceptionToCustomers(IEnumerable customers, Exception ex) { foreach(var customer in customers) customer.SendMessage(ex.Message); } GetCustomers(SendExceptionToCustomers); 

btw, GetCustomers sembra un nome terribile per questa funzione: chiede un’azione, quindi è più simile a DoSomethingToCustomers

EDIT in risposta al commento


Ok, ha senso, quindi ora perché preoccuparsi di avere una funzione GetCustomer? Non riesco a fare la stessa cosa con la tua funzione se io lo rinomassi semplicemente GetCustomer?

Bene, quello che sta succedendo qui è che il chiamante può specificare qualche azione. Supponiamo che GetCustomers sia implementato in questo modo:

 public void GetCustomers(Action, Exception> handleError) { Customer[] customerlist = GetCustomersFromDatabase(); try { foreach(var c in customerList) c.ProcessSomething() } catch (Exception e) { handleError(customerList, e); } } 

quindi puoi chiamare Getcustomers da qualche parte su un programma a riga di comando e passarlo

 GetCustomers((list, exception) => { Console.WriteLine("Encountered error processing the following customers"); foreach(var customer in list) Console.WriteLine(customer.Name); Console.WriteLine(exception.Message); }); 

mentre potresti chiamare GetCustomers da un’applicazione remota, per esempio, e passarlo

 Getcustomers((list, exception) => { // code that emails me the exception message and customer list }) 

Inoltre, il commento di Slak suggerisce un altro motivo per il parametro delegate: GetCustomers recupera i clienti, ma in modo asincrono. Ogni volta che viene effettuato il recupero dei clienti, chiama la funzione che gli viene assegnata con la lista clienti o un’eccezione, se si è verificata un’eccezione.

Un delegato è una class che punta a una o più funzioni. È ansible invocare un’istanza delegata, che chiamerà le funzioni a cui punta.

Nel tuo caso, la funzione GetCustomers prende una seconda funzione come parametro.

La seconda funzione deve contenere due parametri di tipo IEnumerable ed Exception .

Per chiamare GetCustomers , è necessario effettuare una seconda funzione per chiamare, quindi passarlo a un delegato che contiene la seconda funzione.

Per esempio:

 static void GetCustomersCallback(IEnumerable customers, Exception ex) { //Do something... } //Elsewhere: GetCustomers(new Action,Exception>(GetCustomersCallback)); 

Questa chiamata crea una nuova istanza delegato che punta alla funzione GetCustomersCallback e passa tale delegato alla funzione GetCustomers . GetCustomers chiamerà presumibilmente il callback dopo che i clienti hanno terminato il caricamento e passerà i clienti caricati come parametro.
Puoi anche escludere l’istanza del delegato e passare direttamente la funzione:

 GetCustomers(GetCustomersCallback); 

puoi chiamarlo con un lambda

 GetCustomers((cust, ex) => { //do something here} ); 

Delegati .NET: una storia della buonanotte

È solo una versione aggiornata dei puntatori di funzione di C con la possibilità di essere legata a un’istanza di object se si tratta di un puntatore del metodo di object non statico (i C ++ li chiamavano puntatori di metodo quando aggiungevano oggetti e puntatori di funzione insieme).

La firma del tipo può essere resa generica utilizzando le caratteristiche del generico di C #.

Tutta la roba dei generici sta solo templatizzando la firma.

Il nome delegato è scarsamente scelto (a meno che non pensi a tutte le nostre app guidate da framework). Perché l’uso non è sempre “debind”. Spesso è il codice a cui hai delegato delle responsabilità (un iteratore, per esempio) che chiama il “delegato” che hai precedentemente inviato. Ecco perché spesso vedi il termine callback.

Le callback sono state tradizionalmente utilizzate in framework per il codice dell’applicazione da chiamare nel mezzo di un ciclo o quando si verifica un evento particolare. Ti permette di far sì che il tuo codice accada nel mezzo di un altro codice – in effetti, è solo l’unico modo all’interno di un thread.

Ovviamente, i gestori di eventi .NET sono delegati chiamati dal framework in momentjs appropriati, e puoi accettare delegati nelle tue funzioni e chiamarli appropriati per permetterti di rendere il tuo codice un po ‘generico / riutilizzabile / organizzato.

Semplicemente? Puntatori di funzione

Si passa un metodo di annullamento che accetta un object IEnumerable e un’eccezione come parametri …

Dì che hai questo metodo:

 public void DoSomeStuffWithCustomers( IEnumerable customers, Exception exception) { } 

Chiameresti il ​​metodo GetCustomers in questo modo:

 GetCustomers(DoSomeStuffWithCustomers); 

Mi hanno confuso finchè non ho letto:

  1. La spiegazione di Andrew Troelsen su Pro C # 2008 e la piattaforma .Net 3.5
  2. Il capitolo sul pattern Observer in Head First Design Patterns

Quel secondo libro parla di java e non menziona i delegati, ma spiega bene un problema che i delegati aiutano a risolvere: la comunicazione tra le classi.

Fare riferimento al collegamento per i dettagli sui delegati e sugli eventi di DotNet: http://www.codeproject.com/KB/cs/Delegate_To_Event_in_CS.aspx