TIL

[TIL] C# 이벤트(Event)란?

DearGreen 2024. 10. 7. 21:56

C# 이벤트(Event)란?


 

C#의 이벤트는 객체 간의 통신을 가능하게 하고, 특정 행동이나 상태 변화에 대한 반응을 정의한다. 대리자는 이러한 이벤트를 다루기 위한 중요한 구성 요소이다.

이번 글에서는 C#의 이벤트와 대리자의 개념을 정리하고, 대리자가 어떻게 유용하게 사용될 수 있는지를 살펴보자.

 

 

 

대리자에 대한 설명은 지난 포스트를 첨부한다.

https://deargreen.tistory.com/31

 

[TIL] C# 대리자(Delegate)란?

C#  대리자(Delegate)란? C#의 대리자에 대해 알아보자. 마이크로소프트 사의 C# 공식 문서를 참고해 알아보자. [대리자(Delegate) 란?]대리자는 특정 매개 변수 목록 및 반환 형식이 있는 메서드에 대

deargreen.tistory.com

 

여기에 덧붙여, 대리자를 어떤 상황에서 유용하게 사용하는지 정리해 보자.

 

[대리자를 유용하게 사용하는 상황]

1. 이벤트 처리 :

  • 이벤트가 발생하면 관련된 대리자를 통해 특정 메서드가 호출된다. 예를 들어, 버튼 클릭 이벤트에서 클릭한 후의 동작을 정의할 수 있다.

2. 비동기 프로그래밍 :

  • 비동기 작업을 수행할 때 대리자를 사용하여 비동기 메서드를 호출하고 완료할 때 사실을 알릴 수 있다.

3. 콜백 매서드 :

  • 특정 작업이 완료되었을 때 자동으로 호출되는 메서드를 지정할 수 있다. 이는 발행자(Publisher) - 구독자(Subscriber) 모델을 통해 기능을 확장하는 데 유용하다.
  • 서브스크립션 모델? :
    서브스크립션 모델은 객체 간의 통신 방식 중 하나로, 특정 이벤트가 발생했을 때 이를 알리기 위해 구독자(Subscriber)가 이벤트를 등록하는 구조이다. 이 모델은 주로 이벤트 기반 프로그래밍에서 사용된다. 

[이벤트란?]

: C#의 이벤트는 객체 간 통신을 가능하게 하며, 특정 행동이나 상태 변화에 대한 반응을 정의한다. 이벤트는 대리자(delegate)를 통해 처리되며, 대리자는 특정 매개변수와 반환 형식을 가진 메서드에 대한 참조를 제공한다. 이 구조는 이벤트 기반 프로그래밍에서 효율적인 메시지 전달을 가능하게 한다.

 

[이벤트의 구성 요소]

  • 대리자(delegate) : 이벤트를 처리할 메서드를 참조하는 데 사용된다.
  • 이벤트 핸들러(EventHandler) : 이벤트가 발생했을 때 호출되는 메서드이다.

 

[대리자와의 차이점은?]

=> 선언 위치 / 접근성이 다르다.

 

[선언 위치] 

  • 이벤트 : 인터페이스 내부에서 선언할 수 있다! 이는 이벤트가 인터페이스의 일부로서 구현될 수 있도록 한다.
  • 대리자 : 대리자는 클래스나 네임스페이스 내에서 선언할 수 있지만, 인터페이스 내부에서는 선언할 수 없다.

 

[접근성]

  • 이벤트: 이벤트는 public으로 선언되더라도 해당 이벤트가 정의된 클래스 외부에서 직접 호출할 수 없다. 이는 이벤트의 안정성을 높이고, 객체의 상태 변화에 대한 제어를 강화한다.
  • 대리자: 대리자는 호출이 가능하며, 외부에서 직접 메서드를 참조하고 호출할 수 있다.
using System;

// 1. 대리자 선언: 특정 매개변수와 반환 형식을 가진 메서드를 참조할 수 있는 타입
public delegate void MyDelegate(string message);

// 2. 클래스 정의
public class MyClass
{
    // 3. 이벤트 선언: 대리자를 기반으로 하는 이벤트
    public event MyDelegate MyEvent;

    // 4. 이벤트를 발생시키는 메서드
    public void TriggerEvent(string message)
    {
        // 5. 이벤트가 구독되어 있으면 호출
        MyEvent?.Invoke(message); // Null 조건 연산자를 사용하여 안전하게 호출
    }
}

// 6. 구독자 클래스 정의
public class Subscriber
{
    // 7. 이벤트 핸들러: 이벤트 발생 시 호출될 메서드
    public void OnMyEvent(string message)
    {
        Console.WriteLine($"이벤트 발생: {message}");
    }
}

// 8. 프로그램 실행
public class Program
{
    public static void Main()
    {
        MyClass myClass = new MyClass(); // 9. 발행자 인스턴스 생성
        Subscriber subscriber = new Subscriber(); // 10. 구독자 인스턴스 생성
        
        // 11. 이벤트 구독: MyEvent가 발생할 때 OnMyEvent 메서드를 호출하도록 설정
        myClass.MyEvent += subscriber.OnMyEvent;

        // 12. 이벤트 발생: 메시지를 전달하여 이벤트를 트리거
        myClass.TriggerEvent("Hello, World!");

        // 13. 이벤트 구독 해제 (선택적)
        myClass.MyEvent -= subscriber.OnMyEvent; // 구독 해제
    }
}

 

위 코드는 대리자와 이벤트를 사용한 간단한 예시이다. 13번 주석의 구독 해제가 중요한 점이 무엇일까?

  • 이벤트에 구독된 메서드는 발행자 객체가 살아 있는 동안 참조를 유지한다(즉, 메모리를 유지한다). 만약 구독자가 더 이상 필요하지 않거나, 프로그램의 흐름에서 더 이상 호출되지 않는 경우에도 구독이 유지되면 메모리 누수가 발생할 수 있다! 상황에 따른 적절한 구독 해제를 통해 메모리 사용을 최적화할 수 있다!