2009-11-23 2 views

답변

7

이것은 이벤트를 노출하는 클래스의 간단한 구현입니다. 실행 SomeMethod() 유입,

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

제어 흐름에 대해서 :

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

이 클래스는 다음과 같은 것을 사용할 수있다. 새 ChangeNotifier을 생성하고 생성자를 호출합니다. 그러면 값이 개인 num 구성원에 할당됩니다.

그런 다음 += 구문을 사용하여 이벤트를 구독합니다. 이 연산자는 오른쪽에 델리게이트를 가져오고 (이 경우 위임자는 람다 임) 이벤트의 델리게이트 컬렉션에 추가합니다. 이 작업은 ChangeNotifier에 작성한 코드를 실행하지 않습니다. 원하는 경우 이벤트의 addremove 메소드를 통해 사용자 정의 할 수 있지만이를 수행 할 필요는 거의 없습니다.

그런 다음 Number 속성에 대해 몇 가지 간단한 작업을 수행합니다. 먼저 Number 속성의 set 메서드를 value = 10으로 실행하는 10을 할당합니다. 그러나 num 회원은 이미 10으로 평가되므로 초기 조건부 결과는 false로 평가되고 아무 일도 발생하지 않습니다.

그러면 우리는 20과 동일한 작업을 수행합니다. 이번에는 값이 다르므로 새 값을 num에 할당하고 이벤트를 발생시킵니다. 먼저 이벤트가 null이 아닌지 확인합니다. 아무것도 등록되어 있지 않은 경우는 null입니다. null이 아닌 경우 (즉, 에 등록 된 경우) 표준 메소드/위임 구문을 사용하여 호출합니다. 단순히 이벤트의 인수를 사용하여 이벤트를 호출합니다. 그러면 Console.WriteLine()을 수행 할 우리의 람다를 포함하여 이벤트에 가입 한 모든 메소드가 호출됩니다.


는 헨릭 성공적으로 다른 쓰레드가 리스너를 탈퇴하는 동안 하나 개의 스레드가 Number의 세터에있을 수있는 경우에 존재하는 잠재적 경쟁 조건을 nitpicked있다. 아직 이벤트가 작동하는 방법을 이해하지 않는 사람에 대한 일반적인 경우 것으로 생각하지만, 그 가능성에 대해 우려하는 경우,이 라인을 수정하지 않는 :

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

이 같은 될 :

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

Greg에게 감사드립니다. 나는 이런 종류의 대답을 기대하고 있습니다. – Babu

+1

! = null -line의 레이스 조건은 NumberChanged가 다른 스레드보다 더 많은 경우 등록 취소 될 수 있습니다. – Henrik

+1

+1 모든 정보.미안하지만, 소프트웨어 개발에 익숙하지 않습니다. 위의 두 줄의 코드와 편집 된 세 줄은 어떻게 다릅니 까? 다음 3 줄의 코드에서 "this"는 무엇을 언급하며 스레드 문제를 어떻게 해결합니까? 이걸 좀 더 자세히 설명해 주시겠습니까? 감사! –

0

C 배경이있는 경우 대리자를 함수 포인터로 사용할 수 있습니다.

+1

대표는 문제가 생길 이벤트를 이해하는 것은 나를 위해 진짜 문제가되지 않습니다. – 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"); 
    }; 
}