C#의 대리자는 함수를 변수처럼 사용하는 방법일 뿐이다.

C/C++ 에서는 함수 포인터의 개념과 비슷하고, 대부분의 언어에서 Callback(콜백) 개념으로 구현되어 있다.

 

대리자 선언


1. 선언방법

델리게이트_키워드  함수_반환형  델리게이트_이름(함수_시그니처);

 delegate return_type delegate_name(int num1, int num2);

 

[.NET Frame 1.0]

델리게이트_키워드   함수_반환형  델리게이트_이름  =  new 델리게이트_키워드(함수_이름)

 delegate return_type delegate_name = new delegate(funtion);

 

[.NET Frame 2.0]

델리게이트_키워드 함수_ 반환형  델리게이트_이름  = 함수_이름

delegate void delegate_name = funtion;

 

 

2. 시그니처

 

대리자의 시그니처(매개변수 타입, 매개변수 갯수, 리턴 타입)와 

함수의 헤더(function header)가 동일해야 하는 이유는,

이전 포스트의  [매개변수 사용법  2. 객체 전달] 에서와 같이, 대리자는 컴파일러에 의해 특별한 클래스로 변환된다.

 

 

대리자와 함수


대리자는 함수를 변수처럼 사용하는 방법일 뿐이다.

대리자 변수 func을 실행하면서, 매개변수를 넘겨주면, func 변수는 연결된 Add_var( ) 함수를 실행한다. 

이전 포스트를 응용하면, func 대리자 변수명을 아래와 같이 Calc_var( )함수를 실행하듯 사용 가능하다.

A func = new A(Add_var);
// 대리자 변수를 함수처럼 사용하기
Console.WriteLine("매개변수 사용법 4. 계산 결과: " + func(1,2));

 

예제 1

run은 대리자의 변수이지만, 연결된 함수를 실행하듯이 사용 가능하다.

namespace delegate_test2
{
delegate void A(int i);
class MainClass
{
static void Run1(int val)
{
Console.WriteLine("{0}", val);// 콘솔출력 : 1024
}
static void Run2(int value)
{
Console.WriteLine("0x{0:X}", value);// 콘솔출력 : 0x800
}
static void Main(string[] args)
{
A run = run = new A(Run1); // [.NET Frame 1.0]
run(1024); // 대리자 변수명 run 사용
run = Run2; //[.NET Frame 2.0]
run(2048);
}
}
}

 

예제 2

namespace delegate_test3
{
class MySort
{
// 델리게이트 CompareDelegate 선언
public delegate int CompareDelegate(int i1, int i2);
public static void Sort(int[] arr, CompareDelegate comp)
{
if (arr.Length < 2)
return;
Console.WriteLine("함수 Prototype: " + comp.Method);
int ret;
for (int i = 0; i < arr.Length - 1; i++)
{
for (int j = i + 1; j < arr.Length; j++)
{
// 오름차순, 기준값과 다음값의 차가 음수면, 다음값이 " 큰 수" 이므로 교환
// 내림차순, 기준값과 다음값의 차가 양수면, 다음값이 "작은 수" 이므로 교환
ret = comp(arr[i], arr[j]);
if (ret == -1)
{
// 교환
int tmp = arr[j];
arr[j] = arr[i];
arr[i] = tmp;
}
Display(arr);
}
}
Display(arr);
}
static void Display(int[] arr)
{
foreach (var i in arr)
Console.Write(i + " ");
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
(new Program()).Run();
}
void Run()
{
int[] unsortedList = { 3, 7, 2, 10, 1, 21, 6 };
// 오름차순으로 정렬
MySort.CompareDelegate compDelegate = AscendingCompare;
MySort.Sort(unsortedList, compDelegate);
// 내림차순으로 정렬
compDelegate = DescendingCompare;
MySort.Sort(unsortedList, compDelegate);
}
// CompareDelegate 델리게이트와 동일한 Prototype
int AscendingCompare(int num1, int num2)
{
if (num1 == num2)
return 0;
return (num1 - num2) > 0 ? -1 : 1;
}
// CompareDelegate 델리게이트와 동일한 Prototype
int DescendingCompare(int num1, int num2)
{
if (num1 == num2)
return 0;
return (num1 - num2) > 0 ? 1 : -1;
}
}
}