using System;
/*
Delegate Chains(대리자 체인):
여러 개의 메서드를 하나의 델리게이트에 연결하여 순차적으로 호출할 수 있도록 하는 기능.
대리자는 메소드의 참조인데,
대리자 하나가 메소드 여러 개를 동시에 참조할 수 있다.
*/
namespace DelegateChains
{
delegate void Notify(string message); // Notify라는 이름의 대리자를 선언합니다.
// 이 대리자는 문자열 매개변수를 하나 받고
// void를 반환하는 메서드를 참조할 수 있습니다.
class Notifier // Notify 대리자의 인스턴스인 EventOccured를 가지는 클래스 Notifier 선언
{
public Notify EventOccured; // EventOccured라는 Notify 델리게이트 타입의 이벤트를 선언합니다.
// 이 이벤트는 특정 상황이 발생했을 때 다른 객체에 알리는 데 사용됩니다.
}
class EventListener
{
private string name; // EventListener 객체의 이름을 저장할 name이라는 필드 선언
public EventListener(string name) // 생성자
{
this.name = name; // name 필드 초기화
}
public void SomethingHappend(string message) // 이벤트 발생 시 호출될 메서드
// 이 메서드는 이벤트 메시지를 콘솔에 출력합니다.
{
Console.WriteLine($"{name}.SomethingHappened : {message}");
}
}
class MainApp
{
static void Main(string[] args)
{
Notifier notifier = new Notifier(); // Notifier 클래스의 객체를 생성
EventListener listener1 = new EventListener("Listener1"); // EventListener 클래스의 생성자를 호출하여
// EventListener 클래스의 객체를 생성하고,
// listener1이라는 변수에 그 객체를 저장함.
// 괄호안에 인수를 넣는 이유?
// EventListener 클래스의 생성자는 string name이라는 매개변수를 가지고 있습니다.
// 즉, EventListener 객체를 생성할 때 문자열 값을 전달해야 합니다.
// 이 문자열 값은 EventListener 객체의 name 필드에 저장됩니다.
// 이 코드에서는 "Listener1"이라는 문자열을 생성자의 인자로 전달합니다.
// 따라서 listener1 객체의 name 필드에는 "Listener1"이라는 값이 저장됩니다.
EventListener listener2 = new EventListener("Listener2");
EventListener listener3 = new EventListener("Listener3");
// += 연산자를 이용한 체인 만들기
notifier.EventOccured += listener1.SomethingHappend; // += 연산자를 사용하여, EventListener 객체의 SomethingHappend 메서드를
// notifier.EventOccured 대리자에 추가합니다.
// 이렇게 하면 notifier.EventOccured 이벤트가 발생했을 때,
// 추가된 모든 메서드가 순차적으로 호출됩니다.
// listener1의 SomethingHappend 메서드를 EventOccured 이벤트에 추가
notifier.EventOccured += listener2.SomethingHappend; // listener2의 SomethingHappend 메서드를 EventOccured 이벤트에 추가
notifier.EventOccured += listener3.SomethingHappend;
notifier.EventOccured("You've got mail."); // notifier.EventOccured 델리게이트를 호출함.
// 체인에 연결된 모든 메서드가 호출됩니다.
// EventOccured 이벤트 발생
Console.WriteLine();
// -=연산자를 이용한 체인 끊기
notifier.EventOccured -= listener2.SomethingHappend; // EventListener 객체의 SomethingHappend 메서드를
// notifier.EventOccured 델리게이트에서 제거
notifier.EventOccured("Download complete.");
Console.WriteLine();
// +, = 연산자를 이용한 체인 만들기
notifier.EventOccured = new Notify(listener2.SomethingHappend)
+ new Notify(listener3.SomethingHappend); // + 연산자를 사용하여 델리게이트를 결합
notifier.EventOccured("Nuclear launch detected.");
Console.WriteLine();
Notify notify1 = new Notify(listener1.SomethingHappend);
Notify notify2 = new Notify(listener2.SomethingHappend);
// Delegate.Combine() 메서드를 이용한 체인 만들기
notifier.EventOccured =
(Notify)Delegate.Combine(notify1, notify2);
notifier.EventOccured("Fire!!");
Console.WriteLine();
// Delegate.Remove() 메서드를 이용한 체인 끊기
notifier.EventOccured =
(Notify)Delegate.Remove(notifier.EventOccured, notify2);
notifier.EventOccured("RPG!");
}
}
}
/*
출력 결과
Listener1.SomethingHappened : You've got mail.
Listener2.SomethingHappened : You've got mail.
Listener3.SomethingHappened : You've got mail.
Listener1.SomethingHappened : Download complete.
Listener3.SomethingHappened : Download complete.
Listener2.SomethingHappened : Nuclear launch detected.
Listener3.SomethingHappened : Nuclear launch detected.
Listener1.SomethingHappened : Fire!!
Listener2.SomethingHappened : Fire!!
Listener1.SomethingHappened : RPG!
*/
코드 설명
이 C# 코드는 델리게이트 체인을 사용하는 방법을 보여주는 예제입니다. 델리게이트 체인은 여러 개의 메서드를 하나의 델리게이트에 연결하여 순차적으로 호출할 수 있도록 하는 기능입니다. 마치 여러 개의 함수를 하나의 함수처럼 묶어서 사용하는 것과 같습니다.
Notify 델리게이트
delegate void Notify(string message);
Notify라는 이름의 델리게이트를 선언합니다. 이 델리게이트는 문자열 매개변수를 하나 받고 void를 반환하는 메서드를 참조할 수 있습니다.Notifier 클래스
class Notifier
{
public Notify EventOccured; // Notify 델리게이트 타입의 이벤트 EventOccured 선언
}
EventOccured라는 Notify 델리게이트 타입의 이벤트를 선언합니다. 이벤트는 특정 상황이 발생했을 때 다른 객체에 알리는 데 사용됩니다.EventListener 클래스
class EventListener
{
private string name; // EventListener 객체의 이름을 저장할 필드
public EventListener(string name) // 생성자
{
this.name = name; // name 필드 초기화
}
public void SomethingHappend(string message) // 이벤트 발생 시 호출될 메서드
{
Console.WriteLine($"{name}.SomethingHappened : {message}"); // 이벤트 메시지 출력
}
}
name 필드는 EventListener 객체의 이름을 저장합니다.EventListener(string name) 생성자는 name 필드를 초기화합니다.SomethingHappend(string message) 메서드는 이벤트 발생 시 호출될 메서드입니다. 이 메서드는 이벤트 메시지를 콘솔에 출력합니다.MainApp 클래스
class MainApp
{
static void Main(string[] args)
{
Notifier notifier = new Notifier(); // Notifier 객체 생성
EventListener listener1 = new EventListener("Listener1"); // EventListener 객체 생성
EventListener listener2 = new EventListener("Listener2"); // EventListener 객체 생성
EventListener listener3 = new EventListener("Listener3"); // EventListener 객체 생성
notifier.EventOccured += listener1.SomethingHappend; // listener1의 SomethingHappend 메서드를 EventOccured 이벤트에 추가
notifier.EventOccured += listener2.SomethingHappend; // listener2의 SomethingHappend 메서드를 EventOccured 이벤트에 추가
notifier.EventOccured += listener3.SomethingHappend; // listener3의 SomethingHappend 메서드를 EventOccured 이벤트에 추가
notifier.EventOccured("You've got mail."); // EventOccured 이벤트 발생
Console.WriteLine();
notifier.EventOccured -= listener2.SomethingHappend; // listener2의 SomethingHappend 메서드를 EventOccured 이벤트에서 제거
notifier.EventOccured("Download complete."); // EventOccured 이벤트 발생
Console.WriteLine();
notifier.EventOccured = new Notify(listener2.SomethingHappend) // EventOccured 이벤트에 listener2와 listener3의 SomethingHappend 메서드를 추가
+ new Notify(listener3.SomethingHappend);
notifier.EventOccured("Nuclear launch detected."); // EventOccured 이벤트 발생
Console.WriteLine();
Notify notify1 = new Notify(listener1.SomethingHappend); // listener1의 SomethingHappend 메서드를 참조하는 델리게이트 생성
Notify notify2 = new Notify(listener2.SomethingHappend); // listener2의 SomethingHappend 메서드를 참조하는 델리게이트 생성
notifier.EventOccured = (Notify)Delegate.Combine(notify1, notify2); // notify1과 notify2를 결합하여 EventOccured 이벤트에 할당
notifier.EventOccured("Fire!!"); // EventOccured 이벤트 발생
Console.WriteLine();
notifier.EventOccured = (Notify)Delegate.Remove(notifier.EventOccured, notify2); // EventOccured 이벤트에서 notify2를 제거
notifier.EventOccured("RPG!"); // EventOccured 이벤트 발생
}
}
Notifier 객체를 생성하고, 3개의 EventListener 객체를 생성합니다.notifier.EventOccured += listener1.SomethingHappend;와 같이 += 연산자를 사용하여 EventListener 객체의 SomethingHappend 메서드를 notifier.EventOccured 델리게이트에 추가합니다. 이렇게 하면 notifier.EventOccured 이벤트가 발생했을 때, 추가된 모든 메서드가 순차적으로 호출됩니다.notifier.EventOccured("You've got mail.");와 같이 notifier.EventOccured 델리게이트를 호출하면, 체인에 연결된 모든 메서드가 호출됩니다.notifier.EventOccured -= listener2.SomethingHappend;와 같이 -= 연산자를 사용하여 EventListener 객체의 SomethingHappend 메서드를 notifier.EventOccured 델리게이트에서 제거할 수 있습니다.notifier.EventOccured = new Notify(listener2.SomethingHappend) + new Notify(listener3.SomethingHappend);와 같이 + 연산자를 사용하여 델리게이트를 결합할 수도 있습니다.Delegate.Combine(notify1, notify2) 메서드를 사용하여 델리게이트를 결합할 수도 있습니다.Delegate.Remove(notifier.EventOccured, notify2) 메서드를 사용하여 델리게이트에서 특정 메서드를 제거할 수도 있습니다.출력 결과
Listener1.SomethingHappened : You've got mail.
Listener2.SomethingHappened : You've got mail.
Listener3.SomethingHappened : You've got mail.
Listener1.SomethingHappened : Download complete.
Listener3.SomethingHappened : Download complete.
Listener2.SomethingHappened : Nuclear launch detected.
Listener3.SomethingHappened : Nuclear launch detected.
Listener1.SomethingHappened : Fire!!
Listener2.SomethingHappened : Fire!!
Listener1.SomethingHappened : RPG!
EventListener listener1 = new EventListener("Listener1");
괄호안에 인수를 넣는 이유?
EventListener listener1 = new EventListener("Listener1"); 이 코드는 EventListener 클래스의 객체를 생성하는 코드입니다.
new EventListener("Listener1") 부분이 EventListener 클래스의 생성자를 호출하여 객체를 생성하고, listener1이라는 변수에 그 객체를 저장합니다.
EventListener 클래스의 생성자는 string name이라는 매개변수를 가지고 있습니다. 즉, EventListener 객체를 생성할 때 문자열 값을 전달해야 합니다. 이 문자열 값은 EventListener 객체의 name 필드에 저장됩니다.
이 코드에서는 "Listener1"이라는 문자열을 생성자의 인자로 전달합니다. 따라서 listener1 객체의 name 필드에는 "Listener1"이라는 값이 저장됩니다.
EventListener 클래스의 SomethingHappend 메서드는 name 필드의 값을 사용하여 이벤트 메시지를 출력합니다. 따라서 listener1 객체의 SomethingHappend 메서드가 호출되면 "Listener1.SomethingHappened : {message}" 형식의 메시지가 출력됩니다.
요약하자면, EventListener listener1 = new EventListener("Listener1"); 코드는 EventListener 클래스의 객체를 생성하고, 생성자의 인자로 "Listener1"을 전달하여 객체의 name 필드를 초기화합니다.
notifier.EventOccured는 인스턴스이지 않나?
notifier.EventOccured는 이벤트입니다.
Notifier 클래스를 보면 public Notify EventOccured;라고 선언되어 있는데, Notify는 델리게이트이고, 델리게이트 타입으로 선언된 멤버는 이벤트 또는 델리게이트 필드가 될 수 있습니다.
이 경우 EventOccured는 이벤트로 사용됩니다. 이벤트는 특정 상황이 발생했을 때 다른 객체에 알리는 데 사용되며, 델리게이트를 통해 구현됩니다.
notifier.EventOccured += listener1.SomethingHappend;와 같이 += 연산자를 사용하여 이벤트에 메서드를 추가할 수 있고, -= 연산자를 사용하여 이벤트에서 메서드를 제거할 수 있습니다.
이벤트는 델리게이트와 유사하지만, 몇 가지 중요한 차이점이 있습니다.
+= 연산자와 -= 연산자를 사용하여 메서드를 추가하고 제거할 수 있습니다. 델리게이트는 = 연산자를 사용하여 메서드를 할당합니다.이벤트는 델리게이트를 기반으로 구현되지만, 델리게이트와는 다른 개념입니다. 이벤트는 객체 지향 프로그래밍에서 중요한 역할을 하며, 객체 간의 통신을 위한 강력한 도구입니다.