프로그래밍에서 이벤트(Event) 시스템은 사용자 입력이나 시스템의 특정 상태 변화에 반응하는 기능을 개발하는 데 필수적인 요소입니다. 특히 C#에서는 이벤트를 사용하여 객체 간의 소통을 매끄럽게 할 수 있습니다. 이번 글에서는 C#에서 이벤트 시스템을 어떻게 구현하고 활용할 수 있는지 자세히 알아보겠습니다.

C# 이벤트 시스템의 기본 개념

C#의 이벤트는 delegate라는 대리자를 기반으로 작동합니다. 대리자는 메서드를 참조하여 나중에 실행할 수 있도록 도와주는 기능입니다. 이벤트를 선언할 때 대리자를 통해 이벤트 핸들러 메서드를 호출할 수 있습니다.

대리자(Delegate) 선언하기

먼저, 대리자를 선언해서 어떤 형식의 메서드를 이벤트 핸들러로 사용할지 정의해야 합니다.

public delegate void MyEventHandler(object sender, EventArgs e);

여기서 MyEventHandler는 이벤트 핸들러의 시그니처를 정의합니다. object sender는 이벤트를 발생시킨 객체를, EventArgs e는 이벤트의 추가 정보를 전달합니다.

이벤트(Event) 선언하기

이제 대리자를 사용하여 이벤트를 선언합니다.

public class Publisher
{
    public event MyEventHandler MyEvent;
}

이벤트는 event 키워드를 사용하여 정의하며, 대리자를 통해 어떤 메서드를 호출할지를 정하게 됩니다.

이벤트 구독과 발생

이벤트 구독(Subscribe)하기

이벤트를 사용하려면 먼저 이벤트에 메서드를 연결하여 구독해야 합니다. 이를 통해 특정 이벤트가 발생할 때마다 원하는 메서드가 호출됩니다.

public class Subscriber
{
    public void OnMyEvent(object sender, EventArgs e)
    {
        Console.WriteLine("이벤트 발생!");
    }
}

이 메서드를 이벤트에 연결합니다.

Publisher publisher = new Publisher();
Subscriber subscriber = new Subscriber();

publisher.MyEvent += subscriber.OnMyEvent;

이벤트 발생(Raise)하기

이벤트를 발생시키는 것은 대개 클래스 내부에서 이루어집니다.

public void TriggerEvent()
{
    if (MyEvent != null)
    {
        MyEvent(this, EventArgs.Empty);
    }
}

이 메서드는 MyEvent가 null이 아닌 경우(즉, 하나 이상의 메서드가 구독한 경우) 이벤트를 발생시킵니다.

이벤트 시스템 활용 팁

  1. EventArgs 커스터마이징: 기본 EventArgs 클래스를 상속하여 사용자 정의 이벤트 데이터를 만들 수 있습니다.
    public class CustomEventArgs : EventArgs
    {
        public int Data { get; set; }
    }
    
  2. 이벤트 해제하기: 메모리 누수를 방지하기 위해 더 이상 필요 없는 이벤트는 반드시 해제해야 합니다.
    publisher.MyEvent -= subscriber.OnMyEvent;
    
  3. 이벤트 핸들러의 스레드 안전성: 멀티스레드 환경에서는 이벤트를 실행하기 전에 null 체크를 반드시 하고, 가능하다면 lock 문을 이용해 스레드 안전성을 확보하세요.

결론

C#의 이벤트 시스템은 객체 지향 프로그래밍에서 효율적인 메시지 전달을 가능하게 하는 강력한 도구입니다. 대리자와 이벤트는 서로 다른 객체 간에 느슨한 결합을 유지하면서도 유연한 상호작용을 제공합니다. 이 글에서 설명한 기본 개념과 팁을 바탕으로 다양한 시나리오에서 이벤트 시스템을 활용해 보세요. 실전에서 이벤트를 잘 활용한다면 유지 보수성과 확장성이 뛰어난 프로그램을 작성할 수 있을 것입니다.