Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# 대리자(Delegate)란? 개념부터 예제까지 한 번에 이해하기

C# 대리자(Delegate)란 무엇인가?

C#에서 대리자(Delegate)는 하나 이상의 메서드를 참조하는 참조 형식(reference type) 변수입니다. 쉽게 말해 대리자는 '메서드를 가리키는 포인터' 역할을 하며, 런타임에 참조하는 메서드를 자유롭게 변경할 수 있다는 것이 가장 큰 특징입니다.

대리자는 특히 이벤트(event)콜백(callback) 메서드를 구현할 때 널리 활용됩니다. C#의 모든 대리자는 System.Delegate 클래스에서 암시적으로 파생됩니다.

대리자 선언 방법

대리자는 다음과 같은 형식으로 선언합니다.

delegate <반환 타입> <대리자 이름> <매개변수 목록>;

예를 들어 문자열 하나를 매개변수로 받고 반환값이 없는 대리자는 아래처럼 선언할 수 있습니다.

public delegate void printString(string s);

C# 대리자 예제

다음 예제는 대리자를 활용하여 같은 문자열을 콘솔과 파일 두 곳에 각각 출력하는 프로그램입니다.

using System;
using System.IO;
namespace DelegateAppl {
    class PrintString {
        static FileStream fs;
        static StreamWriter sw;
        // 대리자 선언
        public delegate void printString(string s);
        // 콘솔에 출력하는 메서드
        public static void WriteToScreen(string str) {
            Console.WriteLine("The String is: {0}", str);
        }
        // 파일에 출력하는 메서드
        public static void WriteToFile(string s) {
            fs = new FileStream("c:\message.txt",
            FileMode.Append, FileAccess.Write);
            sw = new StreamWriter(fs);
            sw.WriteLine(s);
            sw.Flush();
            sw.Close();
            fs.Close();
        }
        // 대리자를 매개변수로 받아 필요한 시점에 메서드를 호출
        public static void sendString(printString ps) {
            ps("Hello World");
        }
        static void Main(string[] args) {
            printString ps1 = new printString(WriteToScreen);
            printString ps2 = new printString(WriteToFile);
            sendString(ps1);
            sendString(ps2);
            Console.ReadKey();
        }
    }
}

실행 결과

The String is: Hello World

위 코드에서 sendString() 메서드는 실제로 어떤 작업을 수행할지 미리 정하지 않고, 매개변수로 전달받은 대리자가 참조하는 메서드를 그대로 실행합니다. 덕분에 화면 출력용 대리자(ps1)와 파일 출력용 대리자(ps2)를 상황에 맞게 교체해서 전달할 수 있습니다. 이것이 바로 대리자가 제공하는 유연함입니다.

대리자의 핵심 특징 정리

  • 메서드 참조: 대리자는 메서드의 참조를 저장하며, 런타임에 참조 대상을 변경할 수 있습니다.
  • 형식 안전성: 반환 타입과 매개변수 시그니처가 일치하는 메서드만 참조할 수 있어, 잘못된 조합은 컴파일 타임에 잡아줍니다.
  • 멀티캐스트 지원: + 연산자로 여러 메서드를 하나의 대리자에 연결할 수 있으며, 호출 시 등록된 모든 메서드가 순서대로 실행됩니다.
  • 이벤트와 콜백의 기반: C#의 이벤트 모델은 대리자를 기반으로 동작합니다.

참고로 .NET에서는 Action, Func, Predicate 같은 제네릭 내장 대리자를 기본 제공하므로, 간단한 시나리오라면 별도의 대리자를 직접 선언하지 않고도 편리하게 사용할 수 있습니다.