Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/C#] 이벤트 (Event) : 객체에 일어난 사건 알리기 본문

Programming/C#

[Programming/C#] 이벤트 (Event) : 객체에 일어난 사건 알리기

scii 2020. 9. 23. 17:21

알람 시계처럼 어떤 일이 생겼을 때 이를 알려주는 객체가 필요한 경우가 있다. 이런 객체를 만들 때 사용하는 것이 바로 "이벤트 (Event)" 이다. 
이벤트의 동작 원리는 대리자와 거의 흡사하다. 이유는 이벤트는 대리자를 event 한정자로 수식해서 만들기 때문이다.

이벤트 선언 및 사용 절차

  1. 대리자 선언. 대리자는 클래스 밖에 선언해도 되고 안에 선언해도 된다.
  2. 클래스 내에 1에서 선언한 대리자의 인스턴스를 event 한정자로 수식하여 선언.
  3. 이벤트 핸들러를 작성. 이벤트 핸들러는 1에서 선언한 대리자와 일치하는 메소드면 된다.
  4. 클래스의 인스턴스를 생성하고 이 객체의 이벤트에 3에서 작성한 이벤트 핸들러를 등록한다.
  5. 이벤트가 발생하면 이벤트 핸들러가 호출된다.

이벤트 예제

using System;

namespace test
{
    // 1. 대리자 선언. 대리자는 클래스 밖에 선언해도 되고 안에 선언해도 된다.
    delegate void EventHandler(string message);

    class MyNotifier
    {
        // EventHandler는 1에서 선언한 대리자이다.
        public event EventHandler SomethingHappened;

        public void DoSomething(int number)
        {
            int temp = number % 10;
            if (temp != 0 && (temp % 3) == 0)
            {
                // numer가 3, 6, 9로 끝나는 값이 될 때마다 이벤트가 발생한다.
                SomethingHappened(String.Format("{0} : 박수!", number));
            }
        }
    }

    internal class Program
    {
        // SomethingHappened 이벤트에서 사용할 이벤트 핸들러는 EventHandler 대리자의 형식과 
        // 동일한 메소드여야 한다.
        static public void MyHandler(string message)
        {
            Console.WriteLine(message);
        }

        public static void Main(string[] args)
        {
            // SomethingHappened 이벤트에 MyHandler() 메소드를 이벤트 핸들러로 등록한다.
            MyNotifier notifier = new MyNotifier();
            notifier.SomethingHappened += new EventHandler(MyHandler);

            for (int i = 0; i < 30; i++)
            {
                notifier.DoSomething(i);
            }
        }
    }
}


/* 결과

3 : 박수!
6 : 박수!
9 : 박수!
13 : 박수!
16 : 박수!
19 : 박수!
23 : 박수!
26 : 박수!
29 : 박수!

*/

이벤트는 이벤트 처리기를 등록하지 않아도 컴파일 에러가 발생하지 않는다. 그리하여 초기화 하지 않은 이벤트를 쉽게 놓칠 수 있다. 때문에 이벤트를 선언하면 항상 비어 있는 익명 메소드로 미리 초기화를 해두는 것이 좋다. 최악의 경우에도 프로그램이 다운되는 것을 막을 수 있다.

대리자와 이벤트

이벤트는 대리자에 event 키워드로 수식해서 선언한 것에 불과하다. 하지만 다른점이 존재한다. 그것은 이벤트가 대리자와 다르게 외부에서 직접 사용할 수 없다는데 있다.
이벤트는 public 한정자로 선언되어 있어도 자신이 선언되어 있는 클래스 외부에서는 호출이 불가능하다. 반면 대리자는 public이나 internal로 수식되어 있으면 클래스 외부에서라도 얼마든지 호출이 가능하다.

이벤트가 대리자와는 달리 이벤트가 호출될 수 없다는 사실은 견고한 이벤트 기반 프로그래밍에 대한 기대를 가능하게 한다. 예를 들어 외부에서 이벤트를 마구잡이로 발생시킨다고 가정하면 이는 객체의 상태를 허위로 나타내는 것이다. 이런 위협은 대리자로는 막을 수 없다. 이벤트라야 가능하다.
따라서 대리자는 대리자대로 콜백 용도로 사용하고, 이벤트는 이벤트대로 객체의 상태 변화나 사건의 발생을 알리는 용도로 구분하여 사용해야 한다.

Comments