Delegate : 대리자, 특정 지정된 함수를 대신하여 수행해주는 역할, c++ 함수 포인터와 같은 역할.
Delegate는 내부적으로 MulticastDelegate를 상속하므로, 여러 Listener (EventHandler)를 포함 할 수 있다.
Event : Delegate 를 event 한정자로 수식하여 만드는 것.
Delegate 와 크게 다른 점은 이벤트 외부에서 직접 사용할 수 없다는 것이다.
event는 public 한정자로 선언되어 있어도 자신이 선언되어 있는 클래스 외부에서는 호출이 불가능하다.
Delegate 와 EventHandler의 형식은 동일해야 한다.
< Delegate 이용 방식 >
Delegate 만을 이용하여 Eventhandler 수행
del1에 del2 를 추가하여 한번에 두개의 함수를 순차적으로 수행하도록 함.
public delegate int WorkPerformedHandler(int hours, WorkType workType);
static void Main() {
WorkPerformedHandler del1 = new WorkPerformedHandler(WorkPerform1);
WorkPerformedHandler del2 = new WorkPerformedHandler(WorkPerform2);
// 1. Delegate Method
del1(5, WorkType.GenerateReports);
del2(2, WorkType.GenerateReports);
Console.WriteLine();
Console.WriteLine(" adding 2 to 1");
Console.WriteLine();
del1 += del2;
del1(5, WorkType.Golf);
}
static int WorkPerform1 (int hours, WorkType workType)
{
Console.WriteLine("WorkPerformed1 called " + hours.ToString() +" "+ workType.ToString());
return hours + 1;
}
static int WorkPerform2(int hours, WorkType workType)
{
Console.WriteLine("WorkPerformed2 called" + hours.ToString() + " " + workType.ToString());
return hours + 2;
}
< Event & Delegate 이용 방식 >
Custom Eventhandler (WorkPerformedHandler) 와 EventHandler에 대한 각각의 구현 방식이다.
일반적으로 함수를 수행할 때에 delegate에 event listener 가 지정되어 있는지를 확인하고 (값이 null ?) Eventhandler를 수행한다. 그렇지 않으면 오류 발생.
전체 순서는 Event 수행이 필요한 시점에
1. 실제 수행 함수 call (OnWorkPerformed)
2. Delegate null 값 확인
3. Event Raise
- 구현 -
public delegate int WorkPerformedHandler(int hours, WorkType workType);
public class Worker
{
public event WorkPerformedHandler WorkPerformed;
public event EventHandler WorkCompleted;
// 일반적으로 함수의 수행이 완료가 될 때 반환 값을 전달할 수 있다.
// 하지만, 함수를 수행하는 도중에 특정 활동을 하고자 할 때 event를 사용할 수 있다.
public void DoWork(int hours, WorkType workType)
{
for (int i = 0; i < hours; i++)
{
OnWorkPerformed(i + 1, workType);
}
OnWorkCompleted();
//Raise event
}
protected virtual void OnWorkPerformed(int hours, WorkType workType)
{
// 1. event raise like a method
if (WorkPerformed != null)
{
WorkPerformed(hours, workType);
WorkPerformed(this, new WorkPerformedEventArgs(hours, workType));
}
// 2. access to delegate and invoke
var del = WorkPerformed as WorkPerformedHandler;
if (del != null)
{
del(hours, workType);
}
}
protected virtual void OnWorkCompleted()
{
// 1. event raise like a method
if (WorkCompleted != null)
{
WorkPerformed(this, EventArgs.Empty);
}
// 2. access to delegate and invoke
var del = WorkCompleted as EventHandler;
if (del != null)
{
del(this, EventArgs.Empty);
}
}
}
- 적용 -
static void Main()
{
Worker worker = new Worker();
worker.WorkPerformed += new WorkPerformedHandler(worker_WorkPerform);
worker.WorkCompleted += new EventHandler(workerr_WorkCompleted);
worker.DoWork(3, WorkType.GenerateReports);
}
static void worker_WorkPerform(object sender, WorkPerformedEventArgs args)
{
Console.WriteLine("WorkPerform EventArgs : ", args.Hours, args.WorkType);
}
static void worker_WorkCompleted(object sender, EventArgs args)
{
Console.WriteLine("Work Completed");
}
< EventHandler<T> 이용 방식 >
EventHandler를 이용하면 쉽게 이벤트 실행을 위한 custom delegate를 만들수 있으며, Event handler는 sender와 CustomEventArgs로 구성되어 있다.
- 구현 -
public event EventHandler WorkPerformed;
protected virtual void OnWorkPerformed(int hours, WorkType workType)
{
var del = WorkPerformed as EventHandler;
if (del != null)
{
del(this, new WorkPerformedEventArgs(hours, workType));
}
}
- 적용 -
static void Main()
{
Worker worker = new Worker();
worker.WorkPerformed += new EventHandler(worker_WorkPerform);
worker.WorkCompleted += new EventHandler(worker_WorkCompleted);
worker.DoWork(3, WorkType.GenerateReports);
}
static void worker_WorkPerform(object sender, WorkPerformedEventArgs args)
{
Console.WriteLine("WorkPerform EventArgs : ", args.Hours, args.WorkType);
}
static void worker_WorkCompleted(object sender, EventArgs args)
{
Console.WriteLine("Work Completed");
}