본문 바로가기
프로그래밍/C#

[C#] 델리게이트와 이벤트

by 오 복 이 2024. 11. 17.

 델리게이트는 메서드를 가리키는 참조형 변수로, 코드의 유연성과 확장성을 높이는 데 유용합니다. 이벤트는 델리게이트를 기반으로 구현되어 객체 간의 상호작용을 간단하고 안전하게 처리할 수 있게 합니다. 이번 글에서는 델리게이트의 개념과 사용법, 익명 메서드와 람다 표현식, 이벤트의 선언과 구독을 다룹니다.

 

 


1. 델리게이트의 개념과 사용법

**델리게이트(Delegate)**는 메서드 참조를 저장할 수 있는 타입입니다. 이를 사용하면 메서드를 변수처럼 전달하거나 실행할 수 있습니다. 델리게이트는 함수 포인터와 비슷하지만, C#에서는 타입 안전성과 객체 지향의 특성을 유지합니다.

델리게이트 선언, 초기화, 호출

using System;

// 델리게이트 선언: 반환형과 매개변수가 일치해야 함
delegate void GreetDelegate(string name);

class Program
{
    // 델리게이트가 가리킬 메서드
    static void SayHello(string name)
    {
        Console.WriteLine($"안녕하세요, {name}님!");
    }

    static void Main()
    {
        // 델리게이트 인스턴스 생성 및 초기화
        GreetDelegate greet = SayHello;

        // 델리게이트 호출
        greet("홍길동"); // 출력: 안녕하세요, 홍길동님!
    }
}
 

다중 메서드 호출 (Multicast Delegate)

델리게이트는 여러 메서드를 참조할 수 있습니다. 이를 멀티캐스트 델리게이트라고 합니다.

 
 
static void SayGoodMorning(string name)
{
    Console.WriteLine($"좋은 아침입니다, {name}님!");
}

static void Main()
{
    GreetDelegate greet = SayHello;
    greet += SayGoodMorning; // 델리게이트 체인 추가

    // 모든 메서드 호출
    greet("홍길동");
    // 출력:
    // 안녕하세요, 홍길동님!
    // 좋은 아침입니다, 홍길동님!
}
 

💡 멀티캐스트 델리게이트를 사용할 때, 마지막 메서드의 반환 값만 유지됩니다. 반환값이 중요한 경우 단일 델리게이트를 사용해야 합니다.


2. 익명 메서드와 람다 표현식

델리게이트를 초기화할 때 메서드 이름 대신 **익명 메서드(Anonymous Method)**나 **람다 표현식(Lambda Expression)**을 사용할 수 있습니다. 이를 통해 간단한 메서드를 델리게이트에 직접 정의할 수 있습니다.

익명 메서드

static void Main()
{
    // 익명 메서드로 델리게이트 초기화
    GreetDelegate greet = delegate (string name)
    {
        Console.WriteLine($"안녕하세요, {name}님! (익명 메서드 사용)");
    };

    greet("홍길동");
}
 
 

람다 표현식

람다 표현식은 익명 메서드를 간결하게 작성하는 방법입니다. => 연산자를 사용하여 입력 매개변수와 실행 블록을 구분합니다.

 
static void Main()
{
    // 람다 표현식으로 델리게이트 초기화
    GreetDelegate greet = (name) => Console.WriteLine($"안녕하세요, {name}님! (람다 표현식 사용)");

    greet("홍길동");
}
 
 

💡 람다 표현식은 코드가 간결해지고 가독성이 좋아지는 장점이 있어 자주 사용됩니다.


3. 이벤트의 선언과 구독

**이벤트(Event)**는 델리게이트를 기반으로 구현되며, 객체 간의 상호작용을 처리하는 데 사용됩니다. 이벤트는 주로 GUI 애플리케이션이나 비동기 작업에서 상태 변경을 알리는 데 사용됩니다.

이벤트 선언

이벤트는 event 키워드를 사용하여 선언하며, 특정 델리게이트 타입을 기반으로 동작합니다.

 
 
using System;

// 델리게이트 선언
delegate void Notify(string message);

// 이벤트를 포함하는 클래스
class Publisher
{
    // 이벤트 선언
    public event Notify OnNotify;

    public void Publish(string message)
    {
        // 이벤트가 구독된 경우 실행
        if (OnNotify != null)
        {
            OnNotify(message);
        }
    }
}

class Subscriber
{
    public void DisplayMessage(string message)
    {
        Console.WriteLine($"구독자가 받은 메시지: {message}");
    }
}

class Program
{
    static void Main()
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber();

        // 이벤트 구독
        publisher.OnNotify += subscriber.DisplayMessage;

        // 이벤트 발생
        publisher.Publish("새로운 소식이 있습니다!");
        // 출력: 구독자가 받은 메시지: 새로운 소식이 있습니다!
    }
}
 

이벤트 구독 해제

이벤트에서 구독을 해제하려면 -= 연산자를 사용합니다.

publisher.OnNotify -= subscriber.DisplayMessage; // 이벤트 구독 해제
 
 

기본 제공 이벤트 델리게이트: EventHandler와 EventHandler<T>

C#에서는 EventHandler와 EventHandler<T>라는 기본 제공 델리게이트를 사용하여 이벤트를 선언할 수 있습니다. 이는 표준화된 이벤트 패턴을 따르며, 추가 데이터를 전달할 수 있는 기능을 제공합니다.

 
using System;

class Publisher
{
    // EventHandler<T>를 사용한 이벤트 선언
    public event EventHandler<string> OnNotify;

    public void Publish(string message)
    {
        OnNotify?.Invoke(this, message); // 이벤트 발생
    }
}

class Subscriber
{
    public void HandleEvent(object sender, string message)
    {
        Console.WriteLine($"구독자가 받은 메시지: {message}");
    }
}

class Program
{
    static void Main()
    {
        Publisher publisher = new Publisher();
        Subscriber subscriber = new Subscriber();

        // 이벤트 구독
        publisher.OnNotify += subscriber.HandleEvent;

        // 이벤트 발생
        publisher.Publish("새로운 이벤트 발생!");
        // 출력: 구독자가 받은 메시지: 새로운 이벤트 발생!
    }
}
 
 

💡 EventHandler를 사용하면 이벤트 핸들러 메서드에서 sender와 추가 데이터를 받을 수 있어 더욱 유연한 이벤트 처리가 가능합니다.

 


다중 구독자 처리

하나의 이벤트에 여러 구독자를 추가하면 모든 구독자의 핸들러가 호출됩니다.

class Program
{
    static void Main()
    {
        Publisher publisher = new Publisher();

        // 여러 구독자 등록
        publisher.OnNotify += (message) => Console.WriteLine($"구독자 1: {message}");
        publisher.OnNotify += (message) => Console.WriteLine($"구독자 2: {message}");

        publisher.Publish("다중 구독 테스트");
        // 출력:
        // 구독자 1: 다중 구독 테스트
        // 구독자 2: 다중 구독 테스트
    }
}

 


 

델리게이트는 메서드 참조를 관리하고, 이벤트는 델리게이트를 기반으로 객체 간의 상호작용을 처리하는 도구입니다. 익명 메서드와 람다 표현식은 델리게이트를 더 간결하고 유연하게 사용할 수 있도록 하며, 이벤트는 객체 간 통신을 더욱 안전하고 효과적으로 관리할 수 있습니다.

 

728x90
반응형