2009-11-23 20 views

Respuesta

7

Esta es una implementación simple de una clase que expone un evento.

public class ChangeNotifier 
{ 
    // Local data 
    private int num; 

    // Ctor to assign data 
    public ChangeNotifier(int number) { this.num = number; } 

    // The event that can be subscribed to 
    public event EventHandler NumberChanged; 

    public int Number 
    { 
     get { return this.num; } 
     set 
     { 
      // If the value has changed... 
      if (this.num != value) 
      { 
       // Assign the new value to private storage 
       this.num = value; 

       // And raise the event 
       if (this.NumberChanged != null) 
        this.NumberChanged(this, EventArgs.Empty); 
      } 
     } 
    } 
} 

Esta clase se puede utilizar algo como el siguiente:

public void SomeMethod() 
{ 
    ChangeNotifier notifier = new ChangeNotifier(10); 

    // Subscribe to the event and output the number when it fires. 
    notifier.NumberChanged += (s, e) => Console.Writeline(notifier.Number.ToString()); 

    notifier.Number = 10; // Does nothing, this is the same value 
    notifier.Number = 20; // Outputs "20" because the event is raised and the lambda runs. 
} 

cuanto a flujo de control, la ejecución fluye en SomeMethod(). Creamos un nuevo ChangeNotifier y así llamamos a su constructor. Esto asigna el valor de 10 al miembro privado num.

Nos suscribimos al evento utilizando la sintaxis +=. Este operador toma un delegado en el lado derecho (en nuestro caso, ese delegado es un lambda) y lo agrega a la colección de delegados en el evento. Esta operación no ejecuta ningún código que hayamos escrito en el ChangeNotifier. Se puede personalizar a través de los métodos add y remove del evento si lo desea, pero rara vez es necesario hacerlo.

Luego realizamos un par de operaciones simples en la propiedad Number. Primero asignamos 10, que ejecuta el método set en la propiedad Number con value = 10. Pero el miembro num ya está valorado en 10, por lo que el condicional inicial se evalúa como falso y no sucede nada.

Luego hacemos lo mismo con 20. Esta vez, el valor es diferente, por lo que asignamos el nuevo valor a num y activamos el evento. Primero verificamos que el evento no sea nulo. Es nulo si nada se ha suscrito. Si no es nulo (es decir, si algo es suscrito), lo activamos usando la sintaxis estándar de método/delegado. simplemente llamamos al evento con los argumentos del evento. Esto llamará a todos los métodos que se hayan suscrito al evento, incluida nuestra lambda que realizará un Console.WriteLine().


Henrik ha nitpicked con éxito la condición potencial de carrera que si existe un hilo puede estar en colocador Number 's, mientras que otro hilo ha anulado su suscripción a un oyente. No considero que un caso común para alguien que todavía no entienden cómo funcionan los eventos, pero si usted está preocupado por esa posibilidad, modificar estas líneas:

if (this.NumberChanged != null) 
    this.NumberChanged(this, EventArgs.Empty); 

a ser algo como esto:

var tmp = this.NumberChanged; 
if (tmp != null) 
    tmp(this, EventArgs.Empty); 
+1

Gracias Greg. Estoy esperando este tipo de respuesta. – Babu

+1

Condición de carrera en! = Null --line, ya que NumberChanged puede ser anulado por otra cadena si tienes más de ellas. – Henrik

+1

+1 para toda la información.Lo siento, soy nuevo en el desarrollo de software, pero ¿cómo se diferencian las 3 líneas editadas de las 2 líneas de código anteriores, a qué se referirá "esto" en las últimas 3 líneas de código y cómo resolverá el problema? por favor, ¿podrías dar más detalles sobre esto? ¡Gracias! –

0

Si tiene fondo C, puede ver delegar como un puntero para funcionar.

+1

Delegado no será un entendimiento problema.Pero eventos es el verdadero problema para mí. – Babu

+0

La pregunta es sobre eventos. – nawfal

2
class Program 
    { 
     static void Main(string[] args) 
     { 
      Parent p = new Parent(); 
     } 
    } 

    //////////////////////////////////////////// 

    public delegate void DelegateName(string data); 

    class Child 
    { 
     public event DelegateName delegateName; 

     public void call() 
     { 
      delegateName("Narottam"); 
     } 
    } 

    /////////////////////////////////////////// 

    class Parent 
    { 
     public Parent() 
     { 
      Child c = new Child(); 
      c.delegateName += new DelegateName(print); 
      //or like this 
      //c.delegateName += print; 
      c.call(); 
     } 

     public void print(string name) 
     { 
      Console.WriteLine("yes we got the name : " + name); 
     } 
    } 
1
Class A { 
    public delegate void EventHandler(); 

    public static event EventHandler workComplete(); 

    void doWork(){ 
     // DO WORK 
    } 

    void onWorkComplete(){ 
     // Raise event 
     workComplete(); 
    } 
} 

Class Main { 
    A a = new A(); 
    a.workComplete += new() -> { 
     // On Class Complete Work 
     Console.WriteLine("Work Complete"); 
    }; 
} 
Cuestiones relacionadas