2010-08-23 18 views
6

Ho bisogno di aiuto per capire come posso creare un nuovo evento personalizzato. ho letto da here ...C#: comprensione sintassi degli eventi

public delegate void ChangingHandler (object sender, CarArgs ca); 
public event ChangingHandler Change; 
... 
private void car_Change(object sender, CarArgs ca) { 
    MessageBox.Show(ca.Message()); 
} 
... 
car.Change+=new Car.ChangingHandler(car_Change); // add event handler 
... 
Change(this,ca); // call event 

prima, ho davvero ottenere la parte delegato. in un normale declartion variabile,

protected string str1; 

ma qui ho l'extra (ChangingHandler). come posso dare un senso a questo? so che qualcosa di simile a un ChangingHandler sarà usato per gestire l'evento ma mi butta via abit.

public event ChangingHandler Change 

poi

car.Change+=new Car.ChangingHandler(car_Change) 

io non realmente ottenere la sintassi new Car.ChangingHandler(car_Change).

risposta

17

Un evento in C# è un po 'come una raccolta di puntatori del metodo. Dice "hey tutti, se ti importa di me, dammi un puntatore a un metodo che posso invocare, lo terrò e quando avrò voglia di annunciare al mondo cosa succede, invocherò tutti i metodi mi hai dato."

In questo modo, qualcuno può dare all'evento un puntatore al loro metodo, che viene definito "gestore di eventi". L'evento chiamerà questo metodo ogni volta che il proprietario dell'evento ritiene appropriato.

Il delegato, in questo senso, non è altro che dire che tipo di metodo l'evento accetterà. Non puoi avere una persona che dà all'evento un metodo che non accetta argomenti e uno che ne prende 5, non avrebbe idea di come chiamarli. Quindi il delegato è il contratto tra l'evento e il gestore dell'evento, dicendo loro cosa aspettarsi per la firma del metodo.

Nel tuo caso, è probabilmente meglio utilizzare solo EventHandler<T>, che è una costruito nel delegato del modulo void EventHandler<T>(object sender, T eventArgs) per il vostro delegato dell'evento, in questo modo:

public event EventHandler<CarArgs> Change; 

C# in realtà non ha puntatori a funzione nel senso grezzo. I delegati gestiscono invece questo. Sono come puntatori di funzione fortemente tipizzati, orientati agli oggetti. Quando si chiama

car.Change+=new Car.ChangingHandler(car_Change); 

Si stanno dando l'evento un nuovo delegato (puntatore a funzione) che punta al vostro gestore di eventi car_Change, raccontando l'evento di chiamare il metodo car_Change quando è pronto. Il delegato (new ChangeHandler(...) avvolge semplicemente il puntatore al metodo car_Change.

+1

Nota, non è necessario creare in modo esplicito l'istanza del delegato. Puoi fare 'car.Change + = car_Change;' (questo è piuttosto idiomatico) – bruceboughton

3

anche come si scopre che non è necessario il car.Change += new Car.ChangingHandler(car_Change); sytax in quanto non è molto intuitivo come lei ha sottolineato.

Si potrebbe semplicemente scrivere car.Change += car_Change; assumendo car_Change ha la firma del metodo giusto.

11

un evento ha una certa firma. la firma definisce ciò che un ascoltatore deve essere simile in termini di quali parametri e che tipo di ritorno che dovrebbe avere. il presente contratto è espressa attraverso la definizione di un delegato.Dal vostro codice di esempio:

public delegate void ChangingHandler (object sender, CarArgs ca); 

Qui abbiamo definito un delegato per i metodi che prendono un object e CarArgs come parametri, e con un tipo di void ritorno.

Poi abbiamo dichiarare l'evento in quanto tale:

public event ChangingHandler Change; 

Quindi, abbiamo un evento chiamato Change, e gli ascoltatori della manifestazione deve avere la stessa firma del ChangingHandler delegato.

Poi abbiamo bisogno di un metodo listener:

private void car_Change(object sender, CarArgs ca) { 
    MessageBox.Show(ca.Message()); 
} 

Qui possiamo vedere come si ha la stessa firma del ChangingHandler delegato.

finalmente possiamo allegare The Listener per l'evento:

car.Change+=new Car.ChangingHandler(car_Change) 

Quindi, creiamo una nuova ChangingHandler istanza che si riferisce al metodo car_Change, e passare l'istanza delegato all'evento.

Detto questo, mi sento di raccomandare di utilizzare il predefinito EventHandler<T> delegato al posto di creare il proprio:

public event EventHandler<CarArgs> Change; 
0

Un modo grezzo di pensare a questo proposito: il tipo delegato definisce la "forma della funzione" che essere la base del tuo evento. Quindi ChangingHandler è l'aspetto che deve avere la funzione.

Inoltre, un'istanza delegata è come un puntatore a funzione. Pensaci in questi termini.

Il public event ChangingHandler Change definisce un puntatore funzione chiamata Change che punterà funzioni di forma ChangingHandler.

Attualmente, questo puntatore a funzione non punta a nulla. Ecco dove entra il bit car.Change += new Car.ChangingHandler(car_Change).

Prendi questo in due passi. I delegati non sono normali puntatori di funzioni; in realtà sono più simili a pile di puntatori a funzioni, è possibile eseguire più funzioni a un delegato. Questo è il motivo per cui senti le persone parlare più comunemente di "abbonarsi" a un evento; aggiungere la tua funzione all'evento significherà che verrà chiamato quando l'evento verrà attivato. Aggiungi la tua funzione allo "stack" del delegato con l'operatore + =.

Non è possibile aggiungere direttamente una funzione a un delegato, ma è espressa in termini di delegato stesso. Questo viene fatto in modo throwaway rendendo un oggetto new sulla stessa riga aggiungendo la propria funzione all'evento; anche se dal momento che C# 2.0 credo che è possibile aggiungere direttamente le funzioni senza invocare la sintassi new.

1

Gli eventi si basano sul concetto di delegati, un delegato è fondamentalmente una definizione di firma del metodo. È tutto. Come in un'interfaccia, come si definiscono le firme del metodo, ma non le si implementa, lo si fa in tutte le classi che ereditano quell'interfaccia.

Un delegato è una definizione per una firma del metodo, e per i quali è possibile definire come molti il ​​metodo del corpo sei come, per esempio, dato questo (definizione del metodo firma) delegato:

public delegate void ChangingHandler (object sender, CarArgs ca); 

È possibile definire corpi con questo delegato (metodo di definizione di firma) in quanto tale:

public void SomeMethodWhichCreatesADelegateBody() 
{ 
    ChangingHandler myChangingHandler = new ChangingHandler(
     delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ } 
    ); 
} 

questo è un vecchio stile di definire un delegato, però, ora è più leggibile da usare lambda al posto della parola chiave delegato per creare il corpo del metodo come ho fatto io , ma non è importante per il problema.

Ora gli eventi possono essere immaginati come delegati (definizione della firma del metodo) con un array di body a cui si fa riferimento come iscrizione all'evento, la sintassi per la sottoscrizione di un corpo del metodo a un evento è += e c'è anche la sintassi per la rimozione di un corpo di un metodo da una sottoscrizione di eventi che è -=

Quindi questo qui il codice definisce un array di corpo di per il delegato ChangingHandler (metodo di definizione firma):

public event ChangingHandler Change; 

E si può sottoscrivere il corpo di (aggiungerli ai l'array) a questo gruppo di calli ng in un metodo:

public void SomeMethodWhichSubscribesADelegateBodyToAnEvent() 
{ 
    ChangingHandler myChangingHandler = new ChangingHandler(
     delegate(object sender, EventArgs e) { /* the method body for myChangingHandler */ } 
    ); 

    Change += myChangingHandler; 
} 

Ora tutta la ragione per l'evento per avere una serie di bodys metodo, che si arriva a definire e aggiungere come vuoi, è così che ogni volta che si verifica un evento interno dell'oggetto che possiede l'evento, quell'oggetto può eseguire tutti quei metodi per fare tutto ciò che si vuole fare quando si verifica quell'evento. L'oggetto proprietario dell'oggetto fa così:

if (Change != null) // You wouldn't access an array without making sure it wasn't null, would you? 
{ 
    Change(this, new CarArgs()); // This executes every method body in it's array using the signature definition the delegate defined. 
    // The delegate simply exists so this code knows the method signature 
    // so it can know how to call those method body's for you. 
} 
Problemi correlati