C#에서 이벤트는 클래스나 객체에서 특정 작업을 할 때 이벤트를 통해 다른 클래스 또는 객체에 이를 알려주는 통신 메커니즘 입니다. 이번 글에서는 이 이벤트에 대해 알아보겠습니다.
이벤트
보통 이벤트를 발생시키는 클래스를 publisher(게시자, 발행자)라고 하며 이벤트를 받아 처리하는 클래스를 subscriber(구독자) 라고 합니다.
이벤트에는 다음과 같은 규칙이 있습니다.
- 게시자는 이벤트를 발생시킵니다. 구독자는 이벤트에 대해 작업을 수행합니다.
- 한 이벤트에는 여러 구독자가 있습니다. 한 구독자는 여러 이벤트를 처리할 수 있습니다.
- 구독자가 없으면 이벤트는 발생하지 않습니다.
- 이벤트는 보통 GUI에서 단추 클릭, 메뉴 선택 같은 사용자 작업을 표시하는데 사용됩니다.
- 이벤트에 여러 구독자가 있는 경우 이벤트 처리기는 이벤트가 발생할 때 동기적으로 호출됩니다.
- .NET 클래스 라이브러리에서 이벤트는 EventHandler 델리게이트 및 EventArgs 기본 클래스를 기반으로 합니다.
C#에서 EventHandler의 정의를 가보면 아래와 같이 delegate 기반으로 되어 있습니다.
namespace System
{
//
// 요약:
// Represents the method that will handle an event that has no event data.
//
// 매개 변수:
// sender:
// The source of the event.
//
// e:
// An object that contains no event data.
public delegate void EventHandler(object? sender, EventArgs e);
}
결국에 개발자가 이벤트 핸들러를 만들 때 아래와 같이 만들 수 있습니다.
public delegate void Notify(); // 매개변수, 반환값이 없는 형식의 델리게이트 정의
public event Notify? OnEventOccurred = null; // Notify 형식의 이벤트 선언
자세히 보면 이전 글에서 델리게이트 형식으로 사용하는 것과 비슷한데 이벤트로 사용하면 외부에서 직접 호출할 수 없고, 이벤트가 정의된 클래스 내부에서만 호출할 수 있습니다. 또한 외부에서는 이벤트를 구독(+=)하거나 구독 취소(-=)만 가능합니다.
이렇게 만든 이벤트를 구독자들은 아래와 같이 +=, -= 연산자를 통해 구독/구독 취소를 합니다.
OnEventOccurred += GetEvent; // 구독
OnEventOccurred -= GetEvent; // 구독 취소
그리고 이벤트를 호출 할 때 아래와 같은 형식으로 호출합니다.
OnEventOccurred?.Invoke();
예제
아래 프로그램은 이벤트를 이용하여 개발한 발행자 – 구독자 관계를 개발한 프로그램 입니다. 상단의 뉴스, 스포츠, 정치는 발행자이며, 좌측 텍스트 박스에는 선택한 발행자의 마지막 발행 정보를 보여줍니다. ‘발행’ 버튼을 클릭 시, 선택한 발행자는 발행을 합니다.
그리고 하단의 구독자 1 ~ 5를 선택 시 좌측 텍스트 박스에는 선택한 구독자의 총 발행 내용을 볼 수 있으며, ‘구독’, ‘구독 취소’ 버튼을 통해 상단에 발행자를 구독, 구독 취소 할 수 있습니다.
아래 이미지는 구독자2, 4, 5가 스포츠를 구독 한 뒤 스포츠에서 발행을 했을 때 화면입니다.
어려운 프로그램이라 이 글에서는 굳이 코드 설명을 하지 않겠습니다. 프로그램 링크는 아래 깃헙 링크 확인하시기 바랍니다.
github : https://github.com/3001ssw/c_sharp/tree/main/Delegate