C#에서 델리게이트(Delegate)는 특정 시그니처를 가진 메서드를 참조할 수 있는 타입입니다. 이는 메서드를 마치 변수처럼 다루거나, 다른 메서드의 인수로 전달하거나, 컬렉션에 저장하는 등의 작업을 가능하게 합니다. 델리게이트는 타입 안전성을 보장하는 함수 포인터와 유사하며, 콜백 메커니즘이나 이벤트 처리의 기반이 됩니다.
델리게이트 타입 선언
델리게이트를 사용하기 전에 먼저 해당 델리게이트가 참조할 수 있는 메서드의 시그니처(반환 타입과 매개변수 리스트)를 정의해야 합니다. `delegate` 키워드를 사용하여 선언합니다.
// 반환값이 없고 매개변수도 없는 메서드를 참조하는 델리게이트
delegate void MessageNotifier();
// 두 개의 정수 매개변수를 받고 정수를 반환하는 메서드를 참조하는 델리게이트
delegate int Calculator(int num1, int num2);
델리게이트 인스턴스화 및 호출
델리게이트 타입을 선언한 후, 실제 메서드를 델리게이트 인스턴스에 할당하고 호출할 수 있습니다. 할당하려는 메서드는 델리게이트의 시그니처와 정확히 일치해야 합니다.
class Processor
{
// MessageNotifier 델리게이트와 시그니처가 일치하는 메서드
public static void ShowStatus()
{
Console.WriteLine("작업이 완료되었습니다.");
}
// Calculator 델리게이트와 시그니처가 일치하는 메서드
public static int Multiply(int a, int b)
{
return a * b;
}
}
class Program
{
static void Main()
{
// 델리게이트 인스턴스에 메서드 할당
MessageNotifier notify = Processor.ShowStatus;
notify(); // "작업이 완료되었습니다." 출력
Calculator calculate = Processor.Multiply;
int product = calculate(7, 8); // product는 56
Console.WriteLine($"계산 결과: {product}");
}
}
델리게이트를 매개변수로 전달
델리게이트의 강력한 기능 중 하나는 메서드를 다른 메서드의 인수로 전달할 수 있다는 것입니다. 이를 통해 유연한 콜백 패턴을 구현할 수 있습니다.
delegate void ResultHandler(string msg);
class DataAnalyzer
{
// ResultHandler 델리게이트를 매개변수로 받는 메서드
public void ProcessData(int[] data, ResultHandler handler)
{
int sum = 0;
foreach (var item in data)
{
sum += item;
}
handler($"총 합계: {sum}"); // 결과를 콜백 메서드를 통해 전달
}
public static void DisplayResult(string message)
{
Console.WriteLine($"[분석 결과] {message}");
}
public static void LogResult(string message)
{
File.AppendAllText("log.txt", $"{DateTime.Now}: {message}\n");
Console.WriteLine($"로그 파일에 결과 기록됨.");
}
}
class Program
{
static void Main()
{
DataAnalyzer analyzer = new DataAnalyzer();
int[] numbers = { 10, 20, 30, 40 };
// DisplayResult 메서드를 콜백으로 전달
analyzer.ProcessData(numbers, DataAnalyzer.DisplayResult);
// [분석 결과] 총 합계: 100 출력
// LogResult 메서드를 콜백으로 전달
analyzer.ProcessData(numbers, DataAnalyzer.LogResult);
// 로그 파일에 결과 기록됨. (log.txt 파일에 내용 추가)
}
}
익명 메서드와 람다 표현식으로 간소화
C#에서는 델리게이트 인스턴스화를 더 간결하게 할 수 있는 익명 메서드와 람다 표현식을 제공합니다.
delegate double MathFunction(double x);
class Program
{
static void Main()
{
// 익명 메서드를 사용한 델리게이트 인스턴스화 (C# 2.0)
MathFunction square = delegate(double val)
{
return val * val;
};
Console.WriteLine($"5의 제곱: {square(5)}"); // 25.0
// 람다 표현식을 사용한 델리게이트 인스턴스화 (C# 3.0 이상)
MathFunction cube = (input) => input * input * input;
Console.WriteLine($"3의 세제곱: {cube(3)}"); // 27.0
// 매개변수가 없는 델리게이트의 람다
MessageNotifier customNotify = () => Console.WriteLine("사용자 정의 알림!");
customNotify();
}
}
주요 고려사항
- 시그니처 일치: 델리게이트에 할당되는 메서드는 반환 타입과 모든 매개변수의 타입 및 순서가 델리게이트 선언과 정확히 일치해야 합니다.
null참조 방지: 델리게이트 인스턴스가 아무 메서드도 참조하지 않는 상태(null)에서 호출하면NullReferenceException이 발생할 수 있습니다. 호출 전에null여부를 확인하는 것이 좋습니다.- 단일 캐스팅: 이 문서에서 다루는 내용은 단일 메서드만 참조하는 델리게이트입니다. 델리게이트는 여러 메서드를 참조하는 멀티캐스트 델리게이트로도 사용될 수 있으며, 이는 이벤트 처리에서 주로 활용됩니다.
델리게이트를 이해하는 것은 C#에서 이벤트, LINQ, 비동기 프로그래밍 등 고급 기능을 배우는 데 필수적인 기초를 다지는 과정입니다.