: C/C++의 함수 포인터와 비슷한 개념으로, 메서드 파라미터와 리턴 타입에 대한 정의를 한 후, 동일한 파라미터와 리턴 타입을 가진 메서드를 서로 호환해서 불러 쓸 수 있는 기능.
: delegate로 메서드 대리자를 선언해주고 원하는 메서드를 참조시킬 수 있습니다.
쉽게 말하면, 함수를 보관하는 통을 만들고(대리자선언) 그 통안에 함수를 넣고 나중에 통을 가져와서 함수를 실행시키는 방식입니다.
선언 구문
=> 접근제한자 delegate 대상 메서드의 반환타입 타입명(대상 메서드의 매개변수들..);
(예시에선 접근제한자 생략)
delegate void Type1(void); // void func1(void)
delegate int Type2(int, int); // int func2(int, int)
delegate string Type3(double); // string func3(double)
delegate float Type4(int); // float func4(int)
delete는 '타입'이기 때문에 int, string, char, ... 처럼 사용한다.
Type1 F1Delegate;
F1Delegate = new Type1(func1);
Type2 F2Delegate;
F2Delegate = new Type2(func2);
Type3 F3Delegate = func3;
int a = 5;
int a = 5; 처럼 그냥 메서드 넣고, 그 메서드 호출하면 된다.
F1Delegate();, F2Delegate(5, 5); F3Delegate(3.14);
*타입명에 관례적으로 접미사 Delegate를 붙임. 안 붙여도 상관없으나 다 이유가 있다.
namespace Test
{
delegate int CalcDelegate(int x, int y);
class Delegate
{
static int Add(int x, int y) { return x + y; }
static int Sub(int x, int y) { return x - y; }
static void Main(string[] args)
{
CalcDelegate abc = new CalcDelegate(Add);
Console.WriteLine(abc(4, 3)); // 7
abc = Sub;
Console.WriteLine(abc(4, 3)); // 1
}
}
}
이걸 왜 쓸까/ 결론부터 말하면 '콜백(CallBack)메서드"에서 활용하면 드라마틱하다.
콜백
:A라는 메서드를 호출할 때, B라는 메서드를 매개변수로 넘겨주고 A메서드에서 B메서드를 호출하는 것이 상황에서 A메서드를 '콜백메서드'라고 한다. (밑의 예제에서 확인)
namespace Test
{
delegate int CalcDelegate(int x, int y);
class Delegate2
{
static int Add(int x, int y) { return x + y; }
static int Sub(int x, int y) { return x - y; }
public static void Calc(int x, int y, CalcDelegate c)
{
Console.WriteLine(c(x, y));
}
static void Main(string[] args)
{
CalcDelegate Plus = new CalcDelegate(Add);
CalcDelegate Minus = Sub;
Calc(3, 4, Plus);
Calc(3, 4, Minus);
}
}
}
이제는 원하는 메서드를 같이 매개변수로 넘겨주며 해당 기능을 수행한다.
Calc라는 메서드 A가 콜백메서드가 된다. Plus, Minus라는 메서드B를 A에서 호출하니까.
===========================================================
namespace Test
{
delegate T CalcDelegate<T>(T x, T y);
class Delegate3
{
static int Add(int x, int y) { return x + y; }
static double Sub(double x, double y) { return x - y; }
public static void Calc<T>(T x, T y, CalcDelegate<T> c)
{
Console.WriteLine(c(x, y));
}
static void Main(string[] args)
{
CalcDelegate<int> Plus_int = new CalcDelegate<int>(Add);
CalcDelegate<double> Minus_double = Sub;
Calc(3, 4, Plus_int);
Calc(5.1, 3.6, Minus_double);
}
}
}
제네릭 를 이용해서 어떤 타입이든 사용가능한 메서드를 만들었다.
구현에서 object 타입을 이용할 수도 있다.
namespace Test
{
delegate void CalcDelegate(int x, int y);
class delegate_chain
{
static void Add(int x, int y) { Console.WriteLine(x + y); }
static void Subtract(int x, int y) { Console.WriteLine(x - y); }
static void Multiply(int x, int y) { Console.WriteLine(x * y); }
static void Divide(int x, int y) { Console.WriteLine(x / y); }
static void Main(string[] args)
{
CalcDelegate c = Add;
c += Subtract;
c += Multiply;
c += Divide;
c(10, 5);
}
}
}
특이하게 += 연산자를 이용해 delegate 인스턴스를 추가한다.
마찬가지로 -= 연산자를 이용해 인스턴스를 삭제할 수 있다.
(이 모든게 C# 컴파일러의 힘)