C#

[C#]대리자(delegate) 개념, 필요성

DevStory 2021. 9. 22.

C#에서 대리자(delegate)는 메서드를 대신 호출해주는 기법으로 '대신 실행해주는 사람'이라는 국어사전에서 설명하고 있는 의미와 유사합니다.

 

대리자는 메서드의 주소를 참조하고 있어서 메서드를 대신 호출할 수 있는데요.

 

C/C++의 참조 포인터와 유사하지만, 데이터 타입을 안전하게 처리한다는 장점이 있습니다.

 

이번 포스팅에서는 대리자란 무엇인지 그리고 대리자가 왜 필요한지 정리하였습니다.

 


대리자란(delegate)란?

위에서 설명했듯이 대리자는 메서드를 대신해서 호출하는 기법이며, 대리자를 선언하기 위해서는 delegate 키워드를 사용합니다.

한정자 delegate 반환타입 대리자이름 ( 매개변수목록 )

delegate 키워드를 제외하면, 메서드 선언 방법과 동일합니다.

 

대리자가 메서드를 참조 후 호출하는 코드를 작성해보겠습니다.

 

MyDelegate라는 대리자를 선언합니다.

public delegate void MyDeleagte(string msg);

 

그리고 대리자가 참조할 메서드를 생성합니다. 대리자가 참조하는 메서드는 반환 타입과 매개 변수가 대리자와 동일해야 합니다.

public static void MethodA(string msg)
{
  Console.WriteLine("param of MethodA : " + msg);
}

public static void MethodB(string msg)
{
  Console.WriteLine("param of MethodB : " + msg);
}

 

대리자 MyDelegate가 MethodA와 MethodB를 참조 후 호출하는 코드입니다.

MyDelegate del;

del = new MyDelegate(MethodA);
del("Method A Call");

del = new MyDelegate(MethodB);
del("Method B Call");

실행 결과

MyDelegate del;

대리자 인스턴스를 생성하는 코드입니다.

 

del = new MyDelegate(MethodA);

대리자 인스턴스 del은 MethodA 메서드의 주소를 참조합니다.

 

del("Method A Call");

대리자 인스턴스 del은 MethodA 메서드의 주소를 참조하고 있으므로 MehtodA 메서드처럼 사용할 수 있으며, 대리자 del을 호출하면 MethodA 메서드를 호출합니다.

 

del = new MyDelegate(MethodB);

대리자 인스턴스 del은 MethodB 메서드의 주소를 참조합니다.

 

del("Method B Call");

대리자 인스턴스 del은 MethodB 메서드의 주소를 참조하고 있으므로 MethodB 메서드처럼 사용할 수 있으며, 대리자 del을 호출하면 MethodB 메서드를 호출합니다.


대리자의 필요성

다음 코드처럼 직접 메서드를 호출하면 되는데, 왜 대리자를 사용해야 할까요?

MethodA("Method A Call");
MethodB("Method B Call");

 

아래 문제에서 대리자를 사용할 수 있는데요.

실패 시 OnFail() 메서드를 호출하고 성공 시 OnSuccess() 메서드를 호출해야 하는 메서드를 구현
public void SuccessFailHelper(Func<bool> work, Action success, Action failure)
{
   if (work())
      success();
   else
      failure();
}

 

메서드에 메서드를 전달하거나 메서드를 조합해야 하는 경우 Func, Action 대리자를 사용할 수 있는데요.

 

사용 방법은 나중에 따로 포스팅을 할 예정이므로 간단하게 설명하겠습니다.

 

Func <bool> work

반환 타입이 bool 타입인 메서드를 전달받습니다.

반환 타입이 존재하는 메서드를 전달받는 경우 Func 대리자를 사용합니다.

 

Action success, Action failure

반환 타입이 없는 메서드를 전달받습니다.

반환 타입이 없는 메서드를 전달받는 경우 Action 대리자를 사용합니다.

 

SuccessFailHelper 메서드만 보고 대리자의 필요성을 느끼기 어렵기 때문에 다음 코드를 봅시다.

public static bool work1()
{
  //...
}
public static bool work2()
{
  //...
}
public static bool work3()
{
  //...
}

public static void success1()
{
  //...
}
public static void success2()
{
  //...
}

public static void failure1()
{
  //...
}

public static void failure2()
{
  //...
}

public static void SuccessFailHelper(Func<bool> work, Action success, Action failure)
{
  if (work())
    success();
  else
    failure();
}

static void Main(string[] args)
{
  SuccessFailHelper(work1, success1, failure1);
  SuccessFailHelper(work1, success2, failure2);
}

특정 작업을 수행하고 bool 타입을 반환하는 work 메서드, 성공 작업을 수행하는 success 메서드, 실패 작업을 수행하는 failure 메서드가 여러 개 존재한다고 가정합니다.

 

work 메서드, success 메서드, failure 메서드를 조합해야하는 경우 위 코드처럼 Func, Action 대리자로 메서드를 전달받아 SuccessFailHelper 메서드 하나로 처리할 수 있는데요.

 

만약, 대리자를 사용하지 않는 경우 work 메서드, success 메서드, failure 메서드를 조합하는 수많은 메서드를 구현하거나 로직을 작성해야 하므로 코드가 증가한다는 단점이 있습니다.


정리

  • 대리자는 메서드를 대신 호출하는 기법입니다.
  • 대리자는 메서드의 주소를 참조합니다.
  • 대리자를 사용하면 메서드끼리 연결 및 조합이 가능합니다.
반응형

댓글