센로그
[C#] Delegate(대리자) - delegate, Func, Action, Predicate 본문
◆ Delegate
함수를 담는 변수
C#에서 Delegate는 특정 형식의 메서드를 참조할 수 있는 타입이다.
말 그대로 메서드의 '대리자' 역할을 한다.
C++의 함수 포인터와 유사하다.
다음과 같이, delegate 리턴타입 델리게이트명(파라미터) 형식으로 선언한다.
delegate void Calculator(int a, int b);
델리게이트는 같은 반환형 및 같은 매개변수를 갖는 함수를 담을 수 있다.
위의 델리게이트 Caculator는 반환형이 void이고, 파라미터로 (int, int)를 받는 함수를 담을 수 있다.
예시) 다음 코드 실행시 3이 출력된다.
delegate void Calculator(int a, int b);
static void Plus(int a, int b)
{
Console.WriteLine(a + b);
}
static void Main(string[] args)
{
Calculator calc = Plus;
calc(1,2);
}
◆ Delegate parameter
다음과 같이, 델리게이트를 통해 메서드를 매개변수로 전달할 수 있다.
delegate void Calculator(int a, int b);
static void Plus(int a, int b)
{
Console.WriteLine(a + b);
}
static void Minus(int a, int b)
{
Console.WriteLine(a - b);
}
static void MyCalc(Calculator calc, int a, int b) // delegate를 파라미터로 받음
{
calc(a, b);
}
이 경우, 메인에서 다음과 같이 Calculator을 바꿔가며 계산할 수 있다.
static void Main(string[] args)
{
Calculator calc = Plus;
MyCalc(calc, 1, 2); //3
calc = Minus;
MyCalc(calc, 1, 2); //-1
}
◆ C# 내장 delegate
많이 쓰이는 형식에 대해서는, C#에서 미리 정의해둔 델리게이트들이 존재한다.
다음 종류의 내장 델리게이트가 있다. (T와 Tresult는 제네릭 타입)
- Func<T, Tresult>
- Action<T>
- Predicate<T>
이런 델리게이트들은 .NET 프레임워크 메서드들의 파라미터로 많이 사용된다.
Func은 LINQ에서 많이 사용되고, Predicate는 Array나 List의 메서드들에서 많이 사용된다.
◆ Func delegate
Func<T, Tresult>
: 파라미터 T를 받아서 Tresult를 리턴하는 델리게이트
T는 파라미터의 제네릭형 타입(여러개 가능. Func<T1, T2, ..., Tresult>)
Tresult(마지막 제네릭)은 반환형의 제네릭형 타입
다음과 같이 (int, int)를 받아 string을 반환하는 함수가 있다고 하자.
string Plus(int a, int b)
{
return (a + b).ToString();
}
이를 내장 델리게이트 Func으로 받아서 쓰려면 다음과 같이 작성한다.
static void Main(string[] args)
{
Func<int, int, string> func = Plus;
Console.WriteLine(func(1, 2)); //3
}
위 func에서 앞의 두개의 int는 파라미터의 타입이고, 마지막 int는 리턴 타입을 의미한다.
Func는 LINQ에서 Where 조건 판별시 많이 사용된다.
◆ Action delegate
Action<T>
: 파라미터 T를 받고, 반환형이 없는(void) 델리게이트
T는 파라미터의 제네릭형 타입(여러개 가능. Action<T1, T2, ..., Tn>)
다음과 같이 (int, int)를 받고 반환형이 없는 함수가 있다고 하자.
static void Plus(int a, int b)
{
Console.WriteLine(a + b);
}
이를 내장 델리게이트 Action으로 받아서 쓰려면 다음과 같이 작성한다.
static void Main(string[] args)
{
Action<int, int> action = Plus;
action(1,2); //3
}
위 action에서 int, int는 모두 파라미터의 타입을 의미한다.
Console.WriteLine같은 메서드 역시 다음과 같이 대리자를 통해 호출할 수 있다.
Action<string> print = Console.WriteLine;
print("3"); //3
◆ Predicate delegate
Predicate<T>
: T를 받아서 Boolean을 리턴하는 델리게이트
T는 파라미터의 제네릭형 타입(여러개 불가능)
List나 Array 메서드에서 사용됨.
List 클래스 메서드
https://learn.microsoft.com/ko-kr/dotnet/api/system.collections.generic.list-1?view=net-7.0
Array 클래스 메서드
https://learn.microsoft.com/ko-kr/dotnet/api/system.array?view=net-7.0
◆ Delegate Chain
하나의 델리게이트에 여러개의 함수를 연결하여 연쇄적으로 호출하는 것
다음과 같은 델리게이트 void Calculator(int, int) 와 plus(), minus(), multiply(), divide() 함수가 있다고 하자.
delegate void Calculator(int a, int b);
public static void plus(int a, int b)
{
Console.WriteLine(a + b);
}
public static void minus(int a, int b)
{
Console.WriteLine(a - b);
}
public static void multiply(int a,int b)
{
Console.WriteLine(a * b);
}
public static void divide(int a, int b)
{
Console.WriteLine(a / b);
}
이를 연결해서 한번에 호출하고 싶다면 다음과 같이 Delegate.Combine()을 사용한다.
public static void Main(string[] args)
{
//델리게이트 체인
Calculator calc = (Calculator)Delegate.Combine(new Calculator(plus), new Calculator(minus), new Calculator(multiply), new Calculator(divide));
calc(20, 10);
}
출력
◆ Delegate Multicast
Delegate Chain을 통해서 한번에 메서드들을 연결할 수도 있지만, += 또는 -= 연산자를 사용해 메서드 연결을 추가하거나 뺄 수도 있다. 이를 Delegate Multicast라고 부른다.
public static void Main(string[] args)
{
Calculator calculators = plus;
calculators += minus;
calculators += multiply;
calculators += divide;
calculators(20, 10);
}
출력
◆ Delegate + Lambda
델리게이트는 람다식과 함께 쓰곤한다.
람다식은 (매개변수) => {메서드 본문} 형식으로 이루어져있다.
간단한 예시)
public static void Main(string[] args)
{
//델리게이트 + 람다
Calculator calculator0 = (a, b) => Console.WriteLine(a + b);
calculator0(20, 10);
//Func 델리게이트 + 람다
Func<int, int, string> calculator1 = (a, b) => (a + b).ToString();
Console.WriteLine(calculator1(20, 10));
//Action 델리게이트 + 람다
Action<int, int> calculator2 = (a, b) => Console.WriteLine(a + b);
calculator2(20, 10);
//Predicate 델리게이트 + 람다
Predicate<int> calculator3 = (a) => a > 5;
Console.WriteLine(calculator3(20));
}
출력
'게임 > Unity, C#' 카테고리의 다른 글
[C#] LINQ (Language Integrated Query) (2) | 2023.07.03 |
---|---|
[Unity] UnityEvent (유니티 이벤트) (0) | 2023.07.03 |
[Unity] Scriptable Object (스크립터블 오브젝트) (0) | 2023.06.30 |
[Unity] 유니티 라이프사이클 (0) | 2023.06.30 |
[C#] Class vs Struct (0) | 2023.06.29 |