Action<T> Delegate
.NET의 Action<T> delegate는 하나의 파라미터를 받아들이고, 리턴 값이 없는 함수에 사용되는 Delegate이다. Action delegate는 System 네임스페이스에서 제공되는데, 파라미터의 수에 따라 0개부터 16개의 파라미터까지 받아들이는 delegate가 있다. 즉, 파라미터가 없는 Action은 Action delegate, 파라미터가 1개인 Action<T> delegate, 2개인 Action<T1, T2> delegate - 이렇게 16개 파라미터가 있는 Action delegate가 존재한다. 많은 함수의 경우 대개 3~5개의 파라미터까지 있는 걸로 본다면, 상당히 많은 함수에 대한 표준 delegate를 미리 만들어 둔것으로 보면된다. 물론 중요한 특징은 리턴 값이 없어야 한다는 점이다.
class AClass
{
public void Run()
{
// Action<T>
// 입력 : T 타입
// 리턴갑 : 없음
// 기존 메서드 지정
System.Action<string> act = Output;
act("Hello");
// 무명 메서드 지정
Action<string, string> act2 = delegate(string msg, string title)
{
MessageBox.Show(msg, title);
};
act2("No data found", "Error");
// 람다식 사용
Action<int> act3 = code => Console.WriteLine("Code: {0}", code);
act3(1033);
}
void Output(string s)
{
Console.WriteLine(s);
}
}
Func<T, TResult> Delegate
.NET의 Func<T> delegate는 Action delegate와 비슷한데, Action이 리턴값이 없는 경우 사용되는 반면, Func는 반드시 리턴 타입이 - Generic 폼 내에, 즉 템플린 파라미터 안에 - 존재한다. 즉, Func<T>의 T는 리턴값의 타입을 가리키며, 이 경우 입력파라미터는 없다 (일반적으로 T를 입력과 구분하기 위해 TResult로 표현한다). Action과 마찬가지로 입력 파라미터수에 따라 여러 변형이 존재하는데, 입력이 1개인 경우 Func<T, TResult>, 입력이 2개인 경우 Func<T1, T2, TResult> 를 사용한다. Action 과 같이 16개까지 입력파라미터를 받아 들일 수 있다.
//---------------------
// 예제 1
// Func<TResult>
// 입력: 없음
// 리턴: TResult 타입
//---------------------
public void Run()
{
// 메서드 지정
System.Func<bool> f = IsValid;
bool result = f();
// 무명 메서드 지정
Func<bool> fa = delegate
{
return _state == 0;
};
result = fa();
// 람다식 이용
Func<bool> fb = () => _state == 0;
result = fb();
}
bool IsValid()
{
return _state == 0;
}
//---------------------
// 예제 2
// Func<T1, TResult>
// 입력: 1개
// 리턴: TResult 타입
//---------------------
public void Run1()
{
// 메서드 지정
System.Func<int, bool> f = IsValidRange;
bool result = f(10);
// 무명 메서드 지정
Func<int, bool> fa = delegate(int n)
{
return n > 0;
};
result = fa(-1);
// 람다식 이용
Func<int, bool> fb = n => n > 0;
result = fb(-2);
}
bool IsValidRange(int n)
{
return n > 0;
}
Predicate<T> Delegate
.NET의 Predicate<T> delegate는 Action/Func delegate와 비슷한데, 리턴값이 반드시 bool이고 입력값이 T 타입인 delegate이다. Action이나 Func와 달리, 입력 파라미터는 1개이다. 이 특수한 delegate는 .NET의 Array나 List 클래스의 메서드들에서 자주 사용된다. Predicate<T>은 Func<T, bool>와 같이 표현할 수 있는데, Func이 실제로 보다 많은 함수들을 표현할 수 있다. Predicate은 .NET 2.0에서 Array나 List등을 지원하기 위해 만들어 졌으며, 보다 일반화된 Func는 .NET 3.5에서 도입되어 LINQ 등을 지원하도록 만들어졌다.
// Predicate<T>
Predicate<int> p = delegate(int n)
{
return n >= 0;
};
bool res = p(-1);
Predicate<string> p2 = s => s.StartsWith("A");
res = p2("Apple");
Delegate의 사용
Action, Predicate, Func 등의 Delegate는 .NET Framework에서 많이 사용되는데, 많은 경우 이들 Delegate들은 .NET Framework의 기존 메서드들에서 요구되는 파라미터로 사용되는 경우가 많다. 특히, Predicate는 Array나 List의 메서드들에서 많이 사용되고, Func는 LINQ 에서 많이 사용된다. 아래 예제는 Array.Find() 메서드에서 Predicate을 파라미터로 받아들이는 경우와 LINQ의 Where() 메서드에서 Func를 사용한 예이다.
public void Run()
{
int[] arr = { -10, 20, -30, 4, -5 };
// Predicate의 사용
// Array.Find(int[], Predicate<int>)
int pos = Array.Find(arr, IsPositive);
// LINQ에서 Func의 사용
// Where(Func<int, bool> predicate)
var v = arr.Where(n => n >= 0);
}
bool IsPositive(int i)
{
return i >= 0;
}
아래는 Where()메서드의 IntelliSense를 Capture한 것으로 Func의 프로토타입을 볼 수 있다.
'프로그래밍 언어 > C#' 카테고리의 다른 글
C# 리플렉션과 어트리뷰트 (Reflection and Attributes) (0) | 2022.07.08 |
---|---|
C# 전처리기의 모든것 (0) | 2022.07.04 |
C# 배열 복사 방법 (0) | 2022.07.01 |
C# 얕은 복사 깊은 복사 (0) | 2022.07.01 |
C# ?? 및 ??=, ?. 연산자 (0) | 2022.06.29 |