[C#] 대리자 (Delegate)

Learning 

When: 1학년 7월 8일

 

How:

원래 대리자에 대해서는 어느 정도 알고 있기는 했지만, event, 람다식 등 대리자를 완전히 이해해야 사용할 수 있는 문법들을 배우다 보니 자세히 공부해야 할 것 같아 공부하게 되었습니다.

 

Understanding:

  • 대리자란?
    대리자는 메서드를 담는 변수입니다. 대리자 변수를 만든 다음, 그 변수에 메서드들을
    연결하면 변수에 메서드들이 담깁니다. 정확히 말하면 변수는 연결된 메서드들을 참조하는
    것이고, 그 변수는 연결한 메서드들을 한 번에 실행시킬 수도 있습니다.
  • 어떻게 사용할까?
    대리자를 쓰는 것은 조금 갈릴 수도 있지만 한번 알면 어렵지 않습니다.
    일단 대리자는 일반적인 변수를 사용하는 것보다 조금 더 복잡한데, 매개변수와 반환 형식이
    있는 타입을 먼저 선언한 다음 그 형식의 변수를 선언하여 메서드를. 그 이유는 대리자
    타입을 만든 다음, 그 대리자 타입의 변수를 만들고, 그 변수에 메서드를 연결(대입,
    복합 할당 연산자{+=, -=})하여 사용하기 때문입니다. 아래의 코드는
    간단하게
    대리자를 사용하는 코드인데, 순서대로 설명하자면
    1. 대리자 변수의 타입을 만들어 줍니다. 대리자는 메서드를 담는 변수라는 것을 기억하고 
      계신다면 일단 메서드의 반환 형식과 매개 변수는 변수를 만들 때 정의가 돼야 한다는 것도
      유추하실 수 있습니다.
    2. 변수를 생성할 때는 그냥 다른 변수와 같이 접근 제한자, 타입을 정하고 변수명을 쓰면 
      됩니다. (전 짧은 코드를 위해 static으로 선언하여 인스턴스를 만들지 않았습니다.)
    3. 반환 형식과 매개변수가 변수의 타입, 즉 아까 정한 델리게이트 타입의 설정과 같다면
      변수에 매개 변수를 연결시킬 수 있습니다.
    4. 마지막으로 tD(1, 2); 이런 식으로 대리자 변수를 메서드처럼 호출시킬 수도 있지만,
      만약 변수가 null일 경우를 대비하여 ?.Invoke(); 메서드를 사용하면 변수가 null일 땐
      실행이 안되고, null이 아닐 때는 실행되는 안전한 프로그램을 만들 수 있습니다.
internal class Program
{
    private delegate void testDelegate(int a, int b); //대리자 타입 생성
    private static testDelegate tD; //변수 생성

    static void Main(string[] args)
    {
        tD += PlusMethod; // 복합 할당 연산자로 대입 (그냥 '='으로 대입도 가능합니다)

        tD?.Invoke(1, 2); // 실행
    }

    private static void PlusMethod(int a, int b)
    {
        Console.WriteLine(a + b);
    }
}
  • 왜 사용할까?
    메서드들을 한번에 여러 개 사용하는 것쯤은 그냥 메서드를 여러 번 호출시키는 메서드를
    만드는 것으로 충분합니다.
     하지만 대리자는 할 수 있는 일이 더 많을뿐더러, 여러 메서드를
    동시에 호출하는 역할도 그냥 메서드로 하는 것보다 훨씬 잘할 수 있습니다.
  • 여러 메서드 동시에 호출하기
    아래의 코드는 2개의 메서드를 동시에 호출하는 코드입니다. 여기서 대리자를 쓰지 않는다면
    2개의 메서드를 실행하는 메서드를 따로 만들어야 하는데, 이것을 사용하면 유연성이 떨어진다는
    것을 직관적으로 알 수 있고, +=, -=를 사용하지 못하기 때문에 실행 도중에 바꿀 수 없다는 
    대리자와 비교하면 큰 불편함이 생깁니다.
using System;
using System.Diagnostics;

namespace Test
{
    internal class Program
    {
        private delegate void testDelegate(int a, int b);
        private static testDelegate tD;
        static void Main(string[] args)
        {
            Test1 test1 = new Test1();
            Test2 test2 = new Test2();

            tD += test1.PlusMethod;
            tD += test2.MinusMethod;

            tD?.Invoke(1, 2);
        }
    }

    public class Test1
    {
        public void PlusMethod(int a, int b)
        {
            Console.WriteLine(a + b);
        }
    }
    public class Test2
    {
        public void MinusMethod(int a, int b)
        {
            Console.WriteLine(a - b);
        }
    }
}
  • 메서드의 인수로 메서드 넣기
    아래 코드 처럼 대리자 타입을 만들어 두고 타입의 변수를 만든 다음, 그 변수를
    인수로 넣어 메서드 내에서 실행시키는 것이
    가능한데, 이것을 사용하는 방법 중에는 데미지 계산을 예시로 들겠습니다. 
    치명타 데미지, 버프 받았을 때 데미지,  일반 데미지를 계산하는 메서드가 있다고
    가정해 보겠습니다. 그리고 데미지를 받는 메서드에서 데미지를 계산해야 할 때 
    메서드 자체를 인수로 주지 않는다면 오버로딩을 하거나 데미지를 받는 메서드를
    여러 개 만들어야 할 것입니다. 하지만 메서드를 인수로 준다면 데미지 계산은
    따로 인수로 받은 메서드로 하고, 따로 실행할 코드는 데미지를 받는 메서드 안에서
    하는 방식을 사용할 수 있습니다.
using System;
using System.Diagnostics;

namespace Test
{
    internal class Program
    {
        public delegate int testDelegate(int a, int b);
        private static testDelegate tD;
        static void Main(string[] args)
        {
            Test2 test2 = new Test2();
            tD += test2.MinusMethod;
            PlusMethod(1, tD);
        }

        private static void PlusMethod(int a, testDelegate b)
        {
            int c = b(1, 2);

            Console.WriteLine(a + c);
        }
    }
    public class Test2
    {
        public int MinusMethod(int a, int b)
        {
            Console.WriteLine(a - b);
            return a - b;
        }
    }
}

 

Result: 예시로 든 코드 말고도 많은 활용도가 있으니 대리자에 대해서는 완벽하게 이해하는 것이 좋습니다.

'C#' 카테고리의 다른 글

[C#] List  (1) 2025.07.13
[C#] event 키워드  (1) 2025.07.09
[C#] bool 타입이 아닌 값을 반환 형식이 bool인 메서드에서 반환하기  (0) 2025.07.02
[C#] 문자열의 한 문자를 가져오기  (0) 2025.06.28
[C#] enum 키워드  (0) 2025.06.25