2010-08-23 18 views
6

Necesito ayuda para entender cómo puedo crear un nuevo evento personalizado. he leído de here ...C#: comprensión de la sintaxis del evento

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 

primero, yo realmente no entiendo la parte de delegado. en un Declartion variable normal,

protected string str1; 

pero aquí tengo el extra (ChangingHandler). ¿Cómo entiendo esto? Sé que se usará algo así como un ChangingHandler para manejar el evento, pero me da un vuelco.

public event ChangingHandler Change 

continuación

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

Realmente no obtener la sintaxis new Car.ChangingHandler(car_Change).

Respuesta

17

Un evento en C# es una especie de colección de punteros de método. Dice "hola a todos, si te importo, dame un indicador de un método que puedo invocar, lo aferraré, y cuando tenga ganas de anunciar al mundo lo que pasa, invocaré todos los métodos". me diste."

De esta forma, alguien puede darle al evento un puntero a su método, que se conoce como "controlador de eventos". El evento llamará a este método cada vez que el propietario del evento lo considere apropiado.

El delegado, en este sentido, no es más que decir qué tipo de método aceptará el evento. No puede permitir que una persona proporcione al evento un método que no tome argumentos y uno que tome 5, no tendría idea de cómo llamarlos. Entonces, el delegado es el contrato entre el evento y el manejador de eventos, diciéndoles a los dos qué esperar para la firma del método.

En su caso, es probable que sea mejor simplemente usar EventHandler<T>, que está construido en un delegado de la forma void EventHandler<T>(object sender, T eventArgs) para su delegado de eventos, así:

public event EventHandler<CarArgs> Change; 

C# en realidad no tienen punteros a funciones en el sentido puro. Los delegados manejan esto en su lugar. Son como punteros de función orientados a objetos fuertemente tipados. Cuando se llama a

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

Usted está dando el caso de un nuevo delegado (puntero de función) que apunta a su controlador de eventos car_Change, diciéndole al evento para llamar a su método car_Change cuando está listo. El delegado (new ChangeHandler(...) simplemente envuelve el puntero al método car_Change.

+1

Tenga en cuenta que no necesita crear explícitamente la instancia de delegado. Puedes hacer 'car.Change + = car_Change;' (esto es bastante idiomático) – bruceboughton

3

también como resulta que no es necesario el sytax car.Change += new Car.ChangingHandler(car_Change); ya que no es muy intuitivo como usted ha señalado.

Usted simplemente puede escribir car.Change += car_Change; asumiendo car_Change tiene el método correcto de la firma.

11

un evento tiene una cierta firma. Esta firma define lo que es un oyente debe ser similar en términos de qué parámetros y qué tipo de retorno que debe tener. el contrato está expresado mediante la definición de un delegado.A partir de la muestra de código:

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

Aquí hemos definido un delegado para los métodos que toman un object y una CarArgs como parámetros, y con un tipo void retorno.

continuación declarar el evento como tal:

public event ChangingHandler Change; 

Por lo tanto, tenemos un evento llamado Change, y los oyentes del evento debe tener la misma firma que el delegado ChangingHandler.

Entonces necesitamos un método detector:

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

Aquí podemos ver la forma en que tiene la misma firma que el delegado ChangingHandler.

Finalmente podemos adjuntar The Listener al evento:

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

Así, puede crear una nueva instancia ChangingHandler que se refiere al método car_Change, y pasar la instancia delegado al evento.

Dicho todo esto, yo recomendaría usar el predefinida EventHandler<T> delegado en lugar de crear su propia:

public event EventHandler<CarArgs> Change; 
0

Una forma cruda de pensar en ello: el tipo de delegado define la "forma de la función" que se ser la base de tu evento. Así que ChangingHandler es como debe ser la función.

Adelante, una instancia de delegado es como un puntero de función. Piensa en eso en esos términos.

El public event ChangingHandler Change define un puntero de función llamado Change que apuntará a las funciones de la forma ChangingHandler.

Pero actualmente, este puntero a la función apunta a nada. Ahí es donde entra el bit car.Change += new Car.ChangingHandler(car_Change).

Realice esto en dos pasos. Los delegados no son punteros de función normales; en realidad se parecen más a las pilas de punteros de función, puede delegar varias funciones a un delegado. Esta es la razón por la que escuchas a las personas hablar más comúnmente sobre "suscribirse" a un evento; agregar su función al evento significará que se ejecutará cuando se desate el evento. Agregue su función al delegado "stack" con el operador + =.

No se puede simplemente agregar una función directamente a un delegado, sino que se debe expresar en términos del delegado. Esto se hace de una manera desechable haciendo un objeto new en la misma línea donde agrega su función al evento; aunque desde C# 2.0 creo que puede agregar funciones directamente sin invocar la sintaxis new.

1

Los eventos se basan en el concepto de delegados, un delegado es básicamente una definición de firma de método. Eso es todo. Al igual que en una interfaz, cómo defines las firmas de método, pero no las implementas, lo haces en todas las clases que heredan esa interfaz.

Un delegado es una definición para una firma de método, y para el cual se pueden definir tantos del cuerpo del método Es usted como, por ejemplo, teniendo en cuenta esto (definición del método de firma) delegado:

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

Se puede definir cuerpos con este delegado (método de firma definición) como tal:

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

este es un estilo antiguo de definir un delegado sin embargo, ahora es más fácil de leer para usar lambdas en lugar de la palabra clave delegada para crear el cuerpo del método como lo hice , pero eso no es importante para el problema.

Ahora los eventos se pueden imaginar como un delegado (definición de firma de método) con una matriz de cuerpos que se denominan suscripciones al evento, la sintaxis para suscribir un cuerpo de método a un evento es += y también hay sintaxis para la eliminación de un cuerpo de método de una suscripción de eventos que es -=

Así que este código aquí se define una matriz del cuerpo para el delegado ChangingHandler (método de firma definición):

public event ChangingHandler Change; 

Y puede suscribirse de cuerpo (añadirlos a la matriz) a esta agrupación por calli ng en un método:

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

    Change += myChangingHandler; 
} 

Ahora toda la razón para que el evento tiene una gran variedad de bodys método, que se llega a definir y añadir como desee, es por lo que cada vez que un evento ocurre en el interior del objeto que se posee el evento, ese objeto puede ejecutar todos esos métodos para hacer lo que quiera que se haga cuando ocurre ese evento. El objeto que posee el objeto tiene este aspecto:

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. 
}