2009-11-23 2 views

ответ

7

Это простая реализация класса, который предоставляет событие.

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); 
      } 
     } 
    } 
} 

Этот класс может использоваться что-то вроде следующим образом:

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

Относно потока управления, выполнение потоков в SomeMethod(). Мы создаем новый ChangeNotifier и вызываем его конструктор. Это присваивает 10 частному члену num.

Затем мы подписываемся на мероприятие, используя синтаксис +=. Этот оператор принимает делегата с правой стороны (в нашем случае этот делегат является лямбдой) и добавляет его в коллекцию делегатов на мероприятии. Эта операция не выполняет код, который мы написали в ChangeNotifier. Его можно настроить с помощью методов add и remove на мероприятии, если вы хотите, но это редко нужно делать.

Затем мы выполняем пару простых операций на объекте Number. Сначала мы присваиваем 10, который использует метод set на объекте Number с value = 10. Но член num уже оценен в 10, поэтому исходное условие равно false и ничего не происходит.

Затем мы делаем то же самое с 20. На этот раз значение отличается, поэтому мы назначаем новое значение num и запускаем событие. Сначала мы проверим, что событие не равно нулю. Он имеет значение null, если ничто не подписалось на него. Если он не является нулевым (т. Е. Если что-то подписано на него), мы запускаем его с использованием стандартного синтаксиса метода/делегата. мы просто вызываем событие с аргументами события. Это вызовет все методы, которые подписались на мероприятие, включая нашу лямбду, которая будет выполнять Console.WriteLine().


Хенрик успешно nitpicked потенциального состояния гонки, которая существует, если один поток может быть в инкубаторе Number «s в то время как другой поток отписка слушателя. Я не считаю, что в общем случае, для кого-то, кто еще не понимает, как работают события, но если вы беспокоитесь о том, что возможности, изменить эти строки:

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

быть что-то вроде этого:

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

Спасибо, Грег. Я жду такого ответа. – Babu

+1

Условие гонки на! = Null -line, поскольку NumberChanged может быть отписано другим потоком, если у вас их было больше. – Henrik

+1

+1 для всей информации.Извините, я новичок в разработке программного обеспечения, но как отредактированные 3 строки отличаются от вышеуказанных двух строк кода, что будет «это» в последних трех строках кода, и как он будет решать проблему с потоком? пожалуйста, не могли бы вы рассказать об этом? Благодаря! –

0

Если у вас есть фон C, вы можете увидеть делегат как указатель на функцию.

+1

Делегат не будет problem.but понимание событий является реальной проблемой для меня. – Babu

+0

Вопрос о событиях. – 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"); 
    }; 
} 
Смежные вопросы