콜백(Callback)
동기적인 상황에서 어떤 이벤트나 작업의 완료를 알리거나 처리 결과를 전달하는 방식으로 사용된다. C#에서 콜백은 대부분 델리게이트(delegate)를 사용하여 구현된다. 델리게이트는 메서드에 대한 형식 안전한 참조를 제공하며, 비동기적인 상황에서 콜백을 수행하기 위해 이를 활용할 수 있다.
델리게이트(Delegate)
C# 문법 - Delegate(대리자)
1. Delegate 형식은 형식인데, 함수 자체를 넘겨주는 그런 형식! callback 형식 함수 자체를 인자로 넘겨주고 함수를 호출한다. 예시) 사장님(Function)의 비서(Delegate)에게 연락을 요청하지만 받지 않아
code-piggy.tistory.com
콜백과 델리게이트는 C#이 제공하는 관용구의 하나이며 람다 표현식을 사용하는 경우에도 널리 활용된다.
.NET Framework라이브러리는 Predicate<T>, Action<T>, Func<T>와 같은 형태로 자주 사용되는 델리게이트를 정의해두고 있다.
01 Predicate<T>
참/거짓을 반환하는 메서드이다. 주로 컬렉션의 요소를 검사하는데 사용된다.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Predicate<int> isEven = n => n % 2 == 0;
int evenNumber = numbers.Find(isEven);
Console.WriteLine($"Even Number: {evenNumber}"); // Even Number:2 출력
02 Action<T>
매개변수가 하나인 메서들르 나타낸다. 반환값이 없는 경우에 사용된다.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Action<int> printNumber = n => Console.WriteLine(n);
numbers.ForEach(printNumber); // 1 2 3 4 5 출력
03 Func<T,TResult>
Func<T, TResult> 매개변수가 하나인 메서드를 나타낸다. T를 받아들이고 TResult를 반환하는 메서드를 참조할 수 있는 델리게이트이다.
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
Func<int, bool> isGreaterThanThree = n => n > 3;
bool allGreaterThanThree = numbers.TrueForAll(isGreaterThanThree)
Console.WriteLine($"{allGreaterThanThree}"); // False 출력
List<T>는 콜백을 사용하는 다양한 메서드
List<int> numbers = Enumerable.Range(1,200).ToList();
var oddNumbers = numbers.Find( n => n % 2 == 1);
var test = numbers.TrueForAll(n => n < 50 );
numbers.RemoveAll(n => n % 2 == 0 );
numbers.ForEach(item => Console.WriteLine(item));
01 Find()
Predicate<int>형식의 델리게이트를 사용하여 리스트 내에 포함된 요소에대하여 테스트를 수행한다. Find()메서드는 이 콜백을 사용하여 각 항목을 테스트하며, 테스트를 통과한 항목만 반환한다.
02 TrueForAll()
각 요소를 개별적으로 테스트하되 모든 항목이 테스트를 통과한 경우에만 true를 반환한다.
03 RemoveAll()
델리게이트에서 정의한 테스트를 통과한 항목들을 리스트에서 제거한다.
04 Foreach()
리스트 내의 각 요소에 대하여 델리게이트로 지정한 동작을 수행한다. 컴파일러는 람다 표현식을 메서드로 변환한 후 이 메서드를 참조하는 델리게이트를 생성한다.
멀티캐스트(multicast) 델리게이트
델리게이트는 여러 개의 메서드를 동시에 호출할 수 있다. 멀티캐스트 델리게이트를 사용하면 하나의 델리게이트 객체가 여러 메서드를 참조할 수 있다. 델리게이트를 호출하면 참조된 모든 메서드가 순서대로 호출된다.
using System;
class Program
{
delegate void MyPiggy();
static void Main()
{
MyPiggy mypiggy = Piggy1;
mypiggy += Piggy2;
// 멀티캐스트 델리게이트 호출
mypiggy();
}
static void Piggy1()
{
Console.WriteLine("Piggy1");
}
static void Piggy2()
{
Console.WriteLine("Piggy2");
}
}
예외 처리
멀티캐스트 델리게이트를 사용할 때 주의해야 할 점은 하나의 메서드에서 예외가 발생하면 그 즉시 예외 처리가 이루어지며 남은 메서드들은 실행되지 않는다. 그러므 예외가 발생하면 멀티캐스트 델리게이트의 나머지 부분은 실행되지 않게 된다.
using System;
class Program
{
delegate void MyPiggy();
static void Main()
{
MyPiggy myPiggy = Piggy1;
myPiggy += MethodWithException;
// 멀티캐스트 델리게이트 호출
myPiggy();
}
static void Piggy1()
{
Console.WriteLine("Piggy1");
}
static void MethodWithException()
{
Console.WriteLine("MethodWithException");
throw new Exception("Exception in MethodWithException");
}
}
결론
델리게이트는 런탐이에 콜백을 구성하는 최고의 방법이다. 델리게이트를 사용하면 콜백을 사용해야 하는 클라이언트를 더욱 단순하게 구성할 수 있을 뿐 아니라 런타임에 콜백 함수를 구성할 수 있다. 게다가 하나의 델리게이트에 여러 개의 콜백함수를 추가할 수 있다.
본 게시글은 Effective C#을 읽고 정리하였습니다.
'책 > Effective C#' 카테고리의 다른 글
Effective C# - Item9 박싱과 언박싱을 최소화하 (0) | 2023.11.22 |
---|---|
Effective C# - Item 8 이벤트 호출 시에는 null 조건 연산자를 사용하라 (0) | 2023.11.22 |
Effective C# - Item6 nameof() 연산자를 적극 활용하라 (0) | 2023.11.19 |
Effective C# - Item5 문화권별로 다른 문자열을 생성하려면 FormattableString을 사용하라 (0) | 2023.11.16 |
Effective C# - Item4 : string.Format()을 보간 문자열로 대체하라 (0) | 2023.11.10 |
댓글