using System;
/*
이벤트(Event):
어떤 일이 생겼을 때 이를 알려주는 객체가 필요한 경우가 있음.
이벤트는 이런 객체를 만들 때 사용.
대리자(Delegate)를 event 한정자로 수식해서 만듦.
대리자(Delegate) vs 이벤트(Event)?
이벤트는 public 한정자로 수식되어 있어도 자신이 선언된 클래스 외부에서는 호출이 불가능함.
대리자는 public이나 internal 한정자로 수식되어 있으면 클래스 외부에서도 호출이 가능.
이벤트(Event) 사용 이유?
객체의 상태를 허위로 나타낼 수 있는 위험을 이벤트로 막을 수 있음.
대리자: 콜백 용도로 사용(메서드에 대한 참조를 저장하고, 마치 메서드를 변수처럼 사용할 수 있도록 하는 형식)
이벤트: 객체의 상태 변화를 일으키거나 사건의 발생을 알리는 용도로 사용
*/
namespace EventTest
{
// (1) 대리자를 선언합니다. 이 대리자는 클래스 밖에 선언 해도 되고 안에 선언해도 됩니다.
delegate void EventHandler(string message); // EventHandler라는 이름의 델리게이트를 선언합니다.
// 이 델리게이트는 문자열 매개변수를 하나 받고
// void를 반환하는 메서드를 참조할 수 있습니다.
class MyNotifier
{
// (2) 이벤트를 선언합니다.
// 선언한 대리자(EventHandler)의 인스턴스를 event 한정자로 수식해서, '클래스 내'에 선언합니다.
public event EventHandler SomethingHappened; // EventHandler 델리게이트 타입의 이벤트 SomethingHappened 선언
public void DoSomething(int number) // DoSomething() 메서드: 숫자를 입력받아 처리하는 메서드.
// 숫자를 입력받아
// 10으로 나눈 나머지가 0이 아니고 & 3으로 나누어 떨어지면
// SomethingHappened 이벤트를 발생시킵니다
{
int temp = number % 10; // number를 10으로 나눈 나머지를 temp에 저장
if (temp != 0 && temp % 3 == 0) // temp가 0이 아니고 3으로 나누어 떨어지면
{
SomethingHappened(String.Format("{0} : 짝", number)); // SomethingHappened 이벤트 발생
}
}
}
class MainApp
{
// (3) 이벤트 핸들러를 작성합니다. 대리자(EventHandler)의 형식과 동일한 메서드면 됩니다.
static public void MyHandler(string message) // MyHandler() 메서드: 이벤트 처리 메서드입니다.
// message를 콘솔에 출력합니다.
// SomethingHappened 이벤트에서 사용할 이벤트 핸들러(MyHandler)는,
// 대리자(EventHandler)의 형식과 동일한 형식.
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
// (4) 클래스의 인스턴스를 생성하고, 이 인스턴스의 이벤트에 이벤트 핸들러를 등록합니다.
MyNotifier notifier = new MyNotifier(); // MyNotifier 인스턴스를 생성
notifier.SomethingHappened += new EventHandler(MyHandler); // SomethingHappened 이벤트에 MyHandler() 메서드를
// 이벤트 핸들러로 추가(등록)합니다.
// (5) 이벤트가 발생하면 이벤트 핸들러(MyHandler())가 호출됩니다.
for (int i = 1; i < 30; i++) // 1부터 29까지의 숫자를 DoSomething 메서드에 전달
{
notifier.DoSomething(i);
}
}
}
}
/*
실행 결과
3 : 짝
6 : 짝
9 : 짝
13 : 짝
16 : 짝
19 : 짝
23 : 짝
26 : 짝
29 : 짝
*/
코드 설명
이 C# 코드는 이벤트를 사용하는 방법을 보여주는 예제입니다. 이벤트는 특정 상황이 발생했을 때 다른 객체에 알리는 데 사용됩니다. 델리게이트를 사용하여 구현하며, 델리게이트 체인을 통해 여러 개의 메서드를 연결할 수 있습니다.
EventHandler 델리게이트
delegate void EventHandler(string message);
EventHandler라는 이름의 델리게이트를 선언합니다. 이 델리게이트는 문자열 매개변수를 하나 받고 void를 반환하는 메서드를 참조할 수 있습니다.MyNotifier 클래스
class MyNotifier
{
public event EventHandler SomethingHappened; // EventHandler 델리게이트 타입의 이벤트 SomethingHappened 선언
public void DoSomething(int number) // 숫자를 입력받아 처리하는 메서드
{
int temp = number % 10; // number를 10으로 나눈 나머지를 temp에 저장
if (temp != 0 && temp % 3 == 0) // temp가 0이 아니고 3으로 나누어 떨어지면
{
SomethingHappened(String.Format("{0} : 짝", number)); // SomethingHappened 이벤트 발생
}
}
}
SomethingHappened라는 EventHandler 델리게이트 타입의 이벤트를 선언합니다.DoSomething(int number) 메서드는 숫자를 입력받아 10으로 나눈 나머지가 0이 아니고 3으로 나누어 떨어지면 SomethingHappened 이벤트를 발생시킵니다.MainApp 클래스
class MainApp
{
static public void MyHandler(string message) // 이벤트 처리 메서드
{
Console.WriteLine(message); // message 출력
}
static void Main(string[] args)
{
MyNotifier notifier = new MyNotifier(); // MyNotifier 객체 생성
notifier.SomethingHappened += new EventHandler(MyHandler); // MyHandler 메서드를 SomethingHappened 이벤트에 추가
for (int i = 1; i < 30; i++) // 1부터 29까지 반복
{
notifier.DoSomething(i); // DoSomething 메서드 호출
}
}
}
MyHandler(string message) 메서드는 이벤트 처리 메서드입니다. 이 메서드는 message를 콘솔에 출력합니다.Main 메서드에서는 MyNotifier 객체를 생성하고, MyHandler 메서드를 SomethingHappened 이벤트에 추가합니다.for 문을 사용하여 1부터 29까지의 숫자를 DoSomething 메서드에 전달합니다.실행 결과
3 : 짝
6 : 짝
9 : 짝
12 : 짝
15 : 짝
18 : 짝
21 : 짝
24 : 짝
27 : 짝
이 코드는 이벤트를 사용하여 특정 조건을 만족하는 숫자를 출력하는 방법을 보여줍니다. MyNotifier 객체의 DoSomething 메서드에서 숫자를 처리하고, 조건을 만족하면 SomethingHappened 이벤트를 발생시킵니다. MainApp 클래스의 MyHandler 메서드는 이 이벤트를 수신하여 메시지를 출력합니다.
대리자(Delegate) vs 이벤트(Event) ?
C#에서 델리게이트와 이벤트는 둘 다 메서드를 참조하는 형식이지만, 이벤트는 델리게이트를 기반으로 구축된 더욱 특수한 기능을 제공합니다.
델리게이트는 메서드에 대한 참조를 저장하고, 마치 메서드를 변수처럼 사용할 수 있도록 하는 형식입니다. 델리게이트를 사용하면 메서드를 매개변수로 전달하거나, 다른 메서드에서 반환 값으로 사용할 수 있습니다.
이벤트는 특정 상황이 발생했을 때 다른 객체에 알리는 데 사용되는 멤버입니다. 이벤트는 델리게이트를 사용하여 구현되지만, 델리게이트와 달리 외부에서 직접 호출할 수 없습니다. 이벤트는 객체 내부에서만 발생시킬 수 있으며, 이벤트가 발생하면 등록된 메서드들이 호출됩니다.
델리게이트와 이벤트의 주요 차이점
| 특징 | 델리게이트 | 이벤트 |
|---|---|---|
| 목적 | 메서드 참조 | 특정 상황 발생 시 알림 |
| 호출 | 외부에서 호출 가능 | 외부에서 호출 불가능 |
| 접근 범위 | public, private, protected 등 | public 또는 internal |
| 용도 | 메서드 전달, 콜백 함수 구현 | 이벤트 처리 |
이벤트의 장점
예시
// 델리게이트
delegate void MyDelegate(string message);
// 이벤트
public event MyDelegate MyEvent;
이 코드에서 MyDelegate는 문자열 매개변수를 하나 받고 void를 반환하는 메서드를 참조하는 델리게이트입니다. MyEvent는 MyDelegate 델리게이트 타입의 이벤트입니다.
이벤트는 델리게이트를 기반으로 구현되지만, 이벤트는 외부에서 직접 호출할 수 없다는 점에서 델리게이트와 차이가 있습니다. 이벤트는 객체 내부에서만 발생시킬 수 있으며, 이벤트가 발생하면 등록된 메서드들이 호출됩니다.
이벤트는 객체 지향 프로그래밍에서 중요한 개념 중 하나이며, 다양한 상황에서 유용하게 사용될 수 있습니다.
이벤트 핸들러로 등록하는 이유?
이벤트 핸들러를 등록하는 이유는 특정 이벤트가 발생했을 때, 해당 이벤트에 적절히 대응하고 처리하기 위해서입니다.
마치 화재 경보기와 스프링클러 시스템과 같습니다. 화재 경보기는 화재 발생을 감지하고 경보를 울리는 역할을 합니다. 하지만 경보만 울린다면 화재를 진압할 수 없습니다. 스프링클러 시스템은 화재 경보를 감지하고 자동으로 물을 뿌려 화재를 진압하는 역할을 합니다.
이벤트 핸들러는 스프링클러 시스템과 같은 역할을 합니다.
특정 이벤트가 발생하면, 이벤트 핸들러는 해당 이벤트에 대한 정보를 받아서 적절한 처리를 수행합니다.
이벤트 핸들러를 등록하는 방법
C#에서는 += 연산자를 사용하여 이벤트에 이벤트 핸들러를 등록합니다.
// 이벤트 핸들러 등록
notifier.SomethingHappened += new EventHandler(MyHandler);
이벤트 핸들러의 장점
이벤트 핸들러는 이벤트 기반 프로그래밍에서 중요한 역할을 하며, 프로그램의 반응성과 유연성을 향상시키는 데 도움을 줍니다.