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
호출 코드가 참조하는 메서드를 알지 못해도 되기 때문에 동작 단위 캡슐화가 용이하다.
2.1. 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
2.2. 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
2.3. 익명 메서드 또는 람다 식 사용
public delegate void WriteDelegate(string message);
// 익명 메서드
WriteDelegate del = delegate(string message) { Console.WriteLine(message); };
// 람다 식
del += message => Console.WriteLine(message);
2.4. 이벤트 사용
Multicast delegates
는 event에서 많이 사용된다.
event
는 class
, 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
3. 참조 자료