using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Delegate
{
class Program
{
private static void Plus(int a, int b)
{
Console.WriteLine("{0} + {1} = {2}", a, b, a + b);
}
private static void Minus(int a, int b)
{
Console.WriteLine("{0} - {1} = {2}", a, b, a - b);
}
private static void Multiply(int a, int b)
{
Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
}
private static void Divide(int a, int b)
{
if(b != 0)
Console.WriteLine("{0} / {1} = {2}", a, b, a / b);
}
private delegate void Function(int a, int b);
static void Main(string[] args)
{
Function f = null;
f += Plus;
f += Minus;
f += Multiply;
f += Divide;
f(1, 2);
Console.WriteLine("-----------");
f(2, 1);
Console.WriteLine("-----------");
f(3, 0);
}
}
}
인수 두개를 요구하는 함수를 Function으로 정의해 놓고, Function인 f를 만든 후, f에 Plus, Minus 등의 함수를 등록시키면, f를 한번 호출하는 것으로 등록된 함수들을 모두 호출할 수 있습니다.
그런데 사실 이런 일을 하기 위해서는 delegate를 사용할 필요도 없습니다. 이미 필요한 함수들이 정의되어 있기 때문입니다. Action<>이 바로 이미 정의된 delegate들입니다.,
바로 System에 다음과 같이 정의되어 있습니다.
namespace System
{
public delegate void Action();
public delegate void Action<in T1>(T1 arg1);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
public delegate void Action<in T1, in T2, in T3, in T4, in T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12arg12, T13 arg13);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15);
public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
}
위와같이 16개의 인수를 가질 수 있는 함수까지 만들어져 있습니다(사실 이렇게까지 많이 만들 필요는 없을것 같습니다만....)
그러므로 만약 위 프로그램을 Action으로 만든다면 다음과 같습니다.
// private delegate void Function(int a, int b); 딜리게이트 제거
static void Main(string[] args)
{
Action<int, int> f = null; // delegate 대신 인수가 int 2개인 Action 선언
f += Plus;
f += Minus;
f += Multiply;
f += Divide;
f(1, 2);
Console.WriteLine("-----------");
f(2, 1);
Console.WriteLine("-----------");
f(3, 0);
}
최초의 프로그램과 완전히 똑같은 결과가 나오죠.
이와 거의 동일하게 Func<> 역시 존재합니다. Func는 리턴값까지 있는 delegate를 대신합니다.
private static string Plus(int a, int b)
{
return string.Format("{0} + {1} = {2}", a, b, a + b);
}
private static string Minus(int a, int b)
{
return string.Format("{0} - {1} = {2}", a, b, a - b);
}
static void Main(string[] args)
{
Func<int, int, string> f = null; // int 2개를 인수로 하고 string을 리턴하는 함수 선언
f += Plus;
f += Minus;
Console.WriteLine(f(1, 2));
Console.WriteLine(f(2, 1));
}
단, 이 경우에는 f에 등록된 함수들 중 가장 마지막으로 실행된 함수의 리턴값만이 남게 됩니다. 이점을 주의해야 합니다.