본문 바로가기
프로그래밍/Effective C#

Effective C# Item 7 : 델리게이트를 이용하여 콜백을 표현하라

by bantomak 2023. 9. 26.

콜백(CallBack)이란?

프로그래머는 함수를 호출할 때 콜(Call)을 하여 호출한다.

콜백(CallBack)은 콜의 반대되는 개념으로 함수가 언제 실행될지에 대한 권한을 전적으로 위임한다.

기능만을 구현한 채 전달하고 언제 실행될지는 모른다.

 

C#은 이러한 콜백 함수를 구현하기 위해 Delegate 문법을 제공한다.

 

델리게이트를 이용하여 콜백을 표현하라

콜백은 서버가 클라이언트에게 비동기적으로 피드백을 주기 위해서 주로 사용하는 방법이다. 이를 위해 멀티스레딩 기술도 사용되고, 동기적으로 상태를 갱신하는 기법도 활용된다. 콜백은 C#에서 델리게이트를 이용하여 표현된다.

 

델리게이트를 이용하면 타입 안정적인 콜백을 정의할 수 있다. 대부분의 경우에 델리게이트는 event와 함께 사용되지만 반드시 그래야 하는 것은 아니다. 여러 클래스가 상호 통신을 수행해야 할 때 클래스 간의 결합도를 낮추고 싶다면 인터페이스보다 델리게이트를 사용하는 것이 좋다. 관련 링크 델리게이트는 런타임에 통지 대상을 설정할 수 있고, 다수의 클라이언트에게 통지를 보낼 수도 있다. 하나의 델리게이트는 여러 메서드에 대한 참조를 포함할 수 있기 때문이다. 각 메서드는 정적 메서드일 수도 있고, 인스턴스 메서드 일수도 있다. 즉, 델리게이트를 사용하면 통지를 전달하려는 대상이 한 개 일 수도 있고 여러 개 일수도 있다. 런타임에 구성하기 나름이다.

 

콜백과 델리게이트는 C#이 제공하는 관용구의 하나이며 람다 표현식을 사용하는 경우에도 널리 활용된다.

.NET Framework 라이브러리는 Predicate<T>, Action<>, Func<>와 같은 형태로, 자주 사용되는 델리게이트를 정리해두고 있다. 

 

  • Predicate<T>는 조건을 검사하여 부울값을 반환하는 델리게이트
  • Func<>는 여러 개의 매개변수를 받아 단일의 결괏값을 반환하는 델리게이트
    따라서 Func<T, bool>은 Predicate<T>와 동일하다고 볼 수 있다.
  • Action<>은 여러 개의 매개변수를 받지만 반환 타입이 void인 델리게이트

 

public class Program
{
    static void Main(string[] args)
    {
        List<int> numbers = Enumerable.Range(0, 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));
    }
}

 

Find() 메서드는 Predicate<int> 형식의 델리게이트를 사용하여 리스트 내에 포함된 요소에 대하여 테스트를 수행한다. 매우 단순한 콜백의 형태이다. Find() 메서드는 이 콜백을 사용하여 각 항목을 테스트하며, 테스트를 통과한 항목만을 반환한다.

 

TrueForAll() 또한 매우 유사한 방법으로 동작하는데, 각 요소를 개별적으로 테스트하되 모든 항목이 테스트를 통과한 경우에만 true를 반환한다. RemoveAll() 은 델리게이트에서 정의한 테스트를 통과한 모든 항목들을 리스트에서 제거한다.

 

마지막으로 ForEach() 메서드는 리스트 내의 각 요소에 대하여 델리게이트로 지정된 동작을 수행한다. 컴파일러는 람다표현식을 메서드로 변환한 후, 이 메서드를 참조하는 델리게이트를 생성한다.

 

.NET Framework를 사용하다 보면 유사한 개념을 기반으로 하는 다양한 예를 무수히 살펴볼 수 있다. LINQ는 모두 델리게이트를 기반으로 한다. WPF(Windows Presentation Foundation)나 윈폼(WIndows Forms)에서 여러 스레드를 넘나들 경우 반드시 마샬링(Marshaling)이 필요한데, 이 경우에도 콜백이 사용된다. 또한 .NET Framework에서 매개변수로 단일 메서드를 필요로 하는 모든 경우에 람다 표현식을 쓸 수 있도록 델리게이트를 사용한다. 이런 이유로 동일한 구조의 API를 직접 만드는 경우에도 가능한 한 이와 유사한 방식으로 작성하는 것이 좋다.

 

함께 읽으면 좋은 글

 

C# 미리 정의된 Delegate에 대해서

Action Delegate namespace System { // // 요약: // Encapsulates a method that has no parameters and does not return a value. public delegate void Action(); } .NET의 Action delegate는 하나의 파라미터를 받아들이고, 리턴 값이 없는(void)

jettstream.tistory.com

 

출처

 

이펙티브 C# - 예스24

더 나은 C# 코드를 작성하는 새로운 방법 50가지 C#은 전통적인 .NET 기반 개발에서 유니티 게임 엔진으로 개발 영역을 확대하면서 더욱 주목받고 있다. 또한 자마린으로 다양한 모바일 플랫폼에

www.yes24.com

댓글