Favicon

Delegate type

Peponi11/27/20245m

C#
SyntaxTypedelegate

1. Introduction

delegate 형식은 메서드 또는 익명 메서드를 캡슐화할 수 있는 참조 형식이다. 메서드 정의 방법과 유사하게 정의하며, 호환 가능한 시그니쳐를 가진 메서드 또는 람다 식을 이용하여 인스턴스화 할 수 있다. (인스턴스화 할 때는 클래스 객체 생성과 같이 new 키워드를 사용한다)

대리자 호출은 Invoke() 또는 ()를 이용하여 캡슐화 되어있는 메서드를 호출한다. 대리자에게 전달한 매개 변수는 캡슐화된 메서드로 전달되고, 메서드의 반환 값이 다시 대리자의 반환값으로 전달된다.

2. delegate 기본 정의 및 사용법

delegate를 정의하고 사용하는 방법은 아래와 같다.

public delegate string StringCombineDelegate(string str1, string str2);
string Combine(string str1, string str2) => str1 + str2;
StringCombineDelegate del2 = { get; set; }
 
// delegate 인스턴스화 (필드 또는 속성)
 
StringCombineDelegate del = new StringCombineDelegate(Combine);
del2 = new StringCombineDelegate(Combine);
 
// delegate 호출
 
Console.WriteLine(del.Invoke("A", "B"));        // AB
Console.WriteLine(del("A", "B"));               // AB

상기 코드와 같이, delegate 호출은 일반 메서드 호출과 비슷하게 되어있다. delegate 호출 코드가 참조하는 메서드를 알지 못해도 되기 때문에 동작 단위 캡슐화가 용이하다.

3. delegate를 메서드 파라미터로 전달

delegate는 메서드를 캡슐화하기 때문에 메서드 파라미터로 사용이 가능하다.

public delegate void ConsoleWriteDelegate(string message);
void Combine(string str1, string str2, ConsoleWriteDelegate del) => del(str1 + str2);
void ConsoleWrite(string message) => Console.WriteLine(message);
 
// delegate 인스턴스화
 
ConsoleWriteDelegate del = new ConsoleWriteDelegate(ConsoleWrite);
 
// delegate 호출
 
Combine("A", "B", del);     // AB

4. delegate multicasting

System.Delegate는 대리자 형식의 기본 클래스로, 이 클래스는 하나의 메서드 참조가 가능하다. delegate는 여러 개의 메서드 참조 및 호출이 가능한데, 이것을 delegate chain 또는 multicast delegates라 한다. 이 경우 System.Delegate의 하위 클래스인 System.MulticastDelegate 클래스를 참조하게 된다.

대리자 형식은 메서드 참조 수정 편의를 위해 다음 연산자를 지원하며, 변수 연산과 비슷하게 사용한다.

  • +=
  • +
  • =
  • -=
  • -
public delegate void WriteDelegate(string message);
void ConsoleWrite(string message) => Console.WriteLine(message);
void LogWrite(string message) => Log.Write(message);
void UIWrite(string message) => component.Print(message);
 
WriteDelegate del = new WriteDelegate(ConsoleWrite);
del += LogWrite;
del += UIWrite;
 
del("message");     // 실행 순서는 메서드 할당 순서
 
// 실행 순서:
//  ConsoleWrite
//  LogWrite
//  UIWrite

5. 익명 메서드 또는 람다 식 사용

delegate에는 익명 메서드, 람다 식 또한 사용 가능하다.

public delegate void WriteDelegate(string message);
// 익명 메서드
 
WriteDelegate del = delegate(string message) { Console.WriteLine(message); };
 
// 람다 식
 
del += message => Console.WriteLine(message);

6. 이벤트 사용

Multicast delegatesevent에서 많이 사용된다.

  • eventclass, struct 내에서만 호출 가능한 특수 형태의 multicast delegates로 외부에서 호출이 불가하기 때문에 유용하게 사용된다.
  • event를 수신하는 객체는 이벤트 처리 메서드 및 대리자를 만들어 event에 등록한다.
  • event는 활성 시 multicast delegates를 호출하여 등록되어 있는 메서드를 호출하고, 데이터를 전달하도록 한다.
public class MessageEventArgs : EventArgs
{
    public string Message { get; set; }
 
    public MessageEventArgs(string message) => Message = message;
}
// Publishing class
 
public class Sender
{
    public delegate void MessageEventHandler(object sender, MessageEventArgs args);
    public event MessageEventHandler RaiseMessageEvent;
 
    public void Action() => RaiseMessageEvent?.Invoke(this, new MessageEventArgs("Send message"));
}
 
// Receiving class
 
public class Receiver
{
    public Receiver(Sender sender) => sender.RaiseMessageEvent += MessageReceived;
 
    private void MessageReceived(object sender, MessageEventArgs e) => Console.WriteLine($"Receiver received : {e.Message}");
}
Sender sender = new();
Receiver receiver = new(sender);
sender.Action();
 
// Console:
// Receiver received : Send message

7. 참조 자료