Delegate

황현중·2025년 11월 27일

C#

목록 보기
11/24

1. delegate 한 줄 정의

delegate = 메서드를 가리키는 변수 타입

우리가 평소에 쓰는 변수는 이런 느낌이다:

int x = 10;         // x에는 숫자 10이 들어있음
string s = "ABC";   // s에는 문자열 "ABC"가 들어있음

델리게이트는 이렇게 생각하면 된다:

MyDelegate d = ...; // d에는 "어떤 메서드"가 들어있음

즉,
“나중에 호출할 메서드를 변수에 담아두는 것”이 바로 델리게이트다.


2. delegate를 왜 쓰는가?

델리게이트를 쓰는 대표적인 이유는 두 가지다.

  1. 메서드를 매개변수로 넘기고 싶을 때
  2. 동작 방식을 나중에 바꿔 끼우고 싶을 때

예를 들어 배열에서 숫자를 셀 때,

  • 어떤 때는 짝수만 세고 싶고
  • 어떤 때는 홀수만 세고 싶고
  • 어떤 때는 10보다 큰 수만 세고 싶을 수 있다

이럴 때 Count라는 공통 함수 하나만 만들고,
무슨 조건으로 셀지”만 델리게이트로 바꿔 끼울 수 있으면 코드가 훨씬 깔끔해진다.


3. delegate 문법 기본형

델리게이트 타입 선언은 이런 형태다.

delegate 반환형 델리게이트이름(매개변수목록);

예를 들어,

delegate int Calc(int a, int b);

위 한 줄의 의미는 이렇게 해석할 수 있다:

“int 두 개를 받아서 int 하나를 반환하는 메서드를 가리킬 수 있는 타입의 이름을 Calc라고 부르겠다”

Calc타입(자료형 이름)이다.


4. 가장 단순한 delegate 예제 (더하기/빼기)

4-1. 전체 코드

using System;

// int 두 개 받아서 int 하나를 반환하는 메서드를 가리키는 델리게이트 타입
delegate int Calc(int a, int b);

class Program
{
    static void Main()
    {
        Calc calc;   // 델리게이트 변수

        // 1) Add 메서드를 가리키게 함
        calc = Add;
        int r1 = calc(3, 5);   // 내부적으로는 Add(3, 5)가 호출되는 것과 같음
        Console.WriteLine("더하기 결과: " + r1); // 8

        // 2) Sub 메서드를 가리키도록 갈아 끼움
        calc = Sub;
        int r2 = calc(10, 3);  // 내부적으로는 Sub(10, 3)이 호출되는 것과 같음
        Console.WriteLine("빼기 결과: " + r2); // 7

        Console.ReadKey();
    }

    // 델리게이트 시그니처와 같은 메서드들
    static int Add(int a, int b)
    {
        return a + b;
    }

    static int Sub(int a, int b)
    {
        return a - b;
    }
}

4-2. 핵심 포인트 정리

  • Calc → 델리게이트 타입 이름
  • calc → 델리게이트 변수
  • Add, Sub → 실제 메서드
  • calc = Add; → “이제 calcAdd 메서드를 기억하게 한다”는 뜻
  • calc(3, 5) → 실제로는 Add(3, 5)가 호출됨
  • calc = Sub;calc(10, 3) → 이번에는 Sub(10, 3)이 호출됨

정리하면, calc라는 변수는
“현재 어떤 메서드를 호출할지 기억하고 있는 리모컨”이라고 보면 된다.


5. 실전형 예제: 조건을 바꿔가며 Count 하기

이번에는 숫자 배열에서 조건에 맞는 숫자 개수를 세는 예제다.
조건은 델리게이트로 바꿔 끼우는 방식으로 만든다.

5-1. 전체 코드

using System;

// int 하나를 받아서 bool을 반환하는 조건 델리게이트 타입
delegate bool NumberTest(int n);

class Program
{
    static void Main()
    {
        int[] arr = { 3, 5, 4, 2, 6, 7, 8 };

        int evenCount = Count(arr, IsEven);  // 짝수 개수
        int oddCount  = Count(arr, IsOdd);   // 홀수 개수

        Console.WriteLine("짝수 개수: " + evenCount);
        Console.WriteLine("홀수 개수: " + oddCount);

        Console.ReadKey();
    }

    // 조건용 메서드들
    static bool IsEven(int n)
    {
        return n % 2 == 0;
    }

    static bool IsOdd(int n)
    {
        return n % 2 != 0;
    }

    // 델리게이트를 매개변수로 받는 공통 Count 함수
    static int Count(int[] numbers, NumberTest test)
    {
        int count = 0;
        foreach (int n in numbers)
        {
            // test가 가리키는 메서드(IsEven 또는 IsOdd)가 호출됨
            if (test(n))
            {
                count++;
            }
        }
        return count;
    }
}

5-2. 이 예제의 구조

  • delegate bool NumberTest(int n);
    → “int를 받아서 bool을 반환하는 메서드를 가리키는 타입” 정의
  • IsEven → 짝수인지 검사하는 함수
  • IsOdd → 홀수인지 검사하는 함수
  • Count 함수는
    • 배열을 돌면서
    • test(n)true인 것만 세는 공통 로직
    • 어떤 조건 함수를 쓸지는 Main에서 결정

결국 Count는 그대로 두고,
NumberTest 델리게이트에 들어오는 함수만 바꿔서
짝수/홀수/기타 조건을 유연하게 바꿀 수 있는 구조가 된다.



델리게이트는 “메서드를 데이터처럼 넘기고, 나중에 호출하기 위한 도구”다.

0개의 댓글