Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

뭐라도 쓰겠지

25.03.24 / 델리게이트(Delegate) 본문

프로그래밍/C#

25.03.24 / 델리게이트(Delegate)

김데피 2025. 3. 24. 18:29

델리게이트란, 말 그대로 대리자라는 의미를 가지며 특정 메소드(함수)를 참조할 수 있는 타입(Type)이다. 간단히 말해, 델리게이트는 C/C++의 함수 포인터와 유사한 역할을 수행하지만, C#에서는 타입으로 안전하게 관리되는 방식으로 제공된다. 델리게이트를 사용하면 메소드를 변수처럼 전달하거나, 실행 시점을 유연하게 조절하는 등 다양한 구조를 구현할 수 있다.

 

  • 1. 델리게이트의 특징
    • 1-1. 형식 안전(type-safe)
      • C# 델리게이트는 메소드의 시그니처(반환 타입 및 매개변수 목록)와 동일해야만 한다. 이 때문에 컴파일 시점에 오류를 방지할 수 있다.
    • 1-2. 멀티캐스트(Multicast) 지원
      • 하나의 델리게이트 인스턴스에 여러 메소드를 등록할 수 있다. 이렇게 여러 메소드를 등록해 두면 델리게이트를 호출할 때 연결된 모든 메소드가 순차적으로 호출된다.
    • 1-3. 객체 지향적인 처리
      • 델리게이트는 클래스 내무 멤버처럼 취급된다. 클래스나 구조체에서 인스턴스 멤버로 선언하거나, static으로 선언하는 것도 가능하며, 접근 제한자도 지정할 수 있다.
    • 1-4. 이벤트(event)와 긴밀한 연관성
      • C#에서 이벤트 기능은 델리게이트를 기반으로 작동한다. 이벤트는 '어떤 일이 발생했을 때, 연결된 델리게이트들을 호출한다'라는 메커니즘을 제공하며, 델리게이트가 이런 이벤트 구독/발생 구조에서 핵심 역할을 수행한다.
  • 2. 기본 사용 예시
using System;

public delegate int Calculate(int x, int y); 
// 반환 타입: int, 매개변수: (int x, int y)

class Program
{
    static void Main(string[] args)
    {
        // 델리게이트 인스턴스 생성, Add 메서드를 참조
        Calculate calc = Add;
        
        // 메서드 호출
        int result1 = calc(3, 4);
        Console.WriteLine($"Add(3,4) = {result1}");  // 출력: Add(3,4) = 7

        // 델리게이트가 참조하는 메서드를 Subtract로 변경
        calc = Subtract;
        int result2 = calc(10, 5);
        Console.WriteLine($"Subtract(10,5) = {result2}");  // 출력: Subtract(10,5) = 5

        // 멀티캐스트 예시
        calc += Add;  // 여기서 calc에는 Subtract와 Add가 모두 등록
        // calc(10, 5)를 호출하면 Subtract -> Add 순으로 호출
        // 이때 마지막에 호출된 메서드(Add)의 반환값이 최종 결과로 들어옴
        int result3 = calc(10, 5); 
        Console.WriteLine($"Multicast result = {result3}");
    }

    static int Add(int x, int y)
    {
        Console.WriteLine("Add 메서드 호출");
        return x + y;
    }

    static int Subtract(int x, int y)
    {
        Console.WriteLine("Subtract 메서드 호출");
        return x - y;
    }
}
Add(3,4) = 7
Subtract(10,5) = 5
Subtract 메서드 호출
Add 메서드 호출
Multicast result = 15

 

위 예시에서 calc += Add; 구문을 통해 델리게이트 인스턴스에 두 번째 메소드를 추가로 등록할 수 있다. 멀티캐스트에서는 가장 마지막에 호출된 메소드의 반환값이 최종값으로 들어온다는 점을 주의 깊게 봐야 한다.

 

  • 3. 델리게이트의 활용
    • 3-1. 콜백(Callback) 메커니즘
      • 긴 작업을 수행하는 함수에서, 특정 시점에 호출해 줄 메소드를 인자로 넘기고 싶을 때 델리게이트를 사용한다. 예를 들어, 파일 다운로드 라이브러리에서 '다운로드 진행 상황'을 업데이트할 함수(진행률 표시 메소드)를 델리게이트로 전달받아, 다운로드 루프 안에서 적절히 콜백하는 식이다.
    • 3-2. 이벤트(Event) 처리
      • Windows Form, WPF, Unity, ASP.NET 등 C# 기반 GUI/프레임워크에서는 대부분 이벤트로 동작한다. 이벤트를 구독하기 위해 델리게이트(핸들러)를 등록하고, 이벤트가 발생하면 등록된 델리게이트(핸들러)들이 자동으로 실행되는 식이다.
    • 3-3. LINQ와 람다(Lambda)식
      • C#에서 람다 식((x, y) => x + y)을 사용하는 것은 델리게이트의 간편화된 표현이다. 예를들어 Func<int, int, int> 같은 제네릭 델리게이트를 이용하여 LINQ 쿼리나 컬렉션 메소드(Where, Select, OrderbBy)에 람다 식을 넘길 때, 내부적으로 델리게이트를 사용하고 있다.
  • 4. 제네릭 델리게이트
    • C#에서는 자주 쓰이는 델리게이트 패턴을 위해 제네릭 델리게이트를 미리 정의해 두었다.
      • 반환 값을 가지는 델리게이트 패턴 
        • Func<TResult>
        • Func<t, TResult>
        • Func<T1, T2, TResult>
      • 반환 값이 없는 델리게이트 패턴(void 반환)
        • Action<T>
        • Action<T1, T2>
      • 특정 조건을 확인하여 bool을 반환하는 델리게이트 패턴
        • Predicate<T>
    • 예를 들어, 다음 코드에서는 Func<int, int, int> 를 사용해 같은 계산 함수를 람다로 전달할 수 있다.
class Program
{
    static void Main(string[] args)
    {
        Func<int, int, int> calc = (x, y) => x + y;
        Console.WriteLine(calc(2, 3)); // 5

        calc = (x, y) => x - y;
        Console.WriteLine(calc(5, 2)); // 3
    }
}

 

정리하자면 델리게이트는 C#에서 메소드를 가리키는 형식으로, 형식 안정성과 멀티캐스트 등을 지원한다. 콜백, 이벤트, 함수의 동적 할당, 람다 식 및 LINQ 표현식 등 광범위하게 활용된다. C#에서 제공하는 제네릭 델리게이트를 자주 사용하면 코드가 간결해지고 재사용성도 좋아진다. 이벤트는 델리게이트를 기반으로 이루어진 것으로, GUI나 게임, 서버 통신 등 이벤트 기반 프로그래밍에 광범위하게 쓰인다.