다음 조건을 만족하는 콜백 패턴을 구현하려고 할 때, event 예약어를 사용할 수 있다.
다음의 예시를 통해 delegate에서 event로 발전시키는 과정을 소개하겠다.
✍ 샘플코드
class Test
{
static void Main(string[] args)
{
PrimeGenerator generator = new PrimeGenerator();
PrimeGenerator.PrimeDelegate callbackPrint = PrintPrime;
generator.AddDelegate(callbackPrint);
PrimeGenerator.PrimeDelegate callbackSum = SumPrime;
generator.AddDelegate(callbackSum);
generator.Run(10);
Console.WriteLine("====================new trial==================");
generator.RemoveDelegate(callbackSum);
generator.Run(15);
}
//콜백 메서드 1
static void PrintPrime(int num)
{
Console.WriteLine("발견된 소수 :"+num);
}
static int sum;
//콜백메서드 2
static void SumPrime(int num)
{
sum += num;
Console.WriteLine("누적된 소수의 합 : "+sum);
}
}
class PrimeGenerator
{
public delegate void PrimeDelegate(int num);//콜백메서드 묶음을 담을 델리게이트 선언
PrimeDelegate callbacks; //콜백메서드의 묶음
public void AddDelegate(PrimeDelegate callback) //구독
{
callbacks = Delegate.Combine(callbacks,callback) as PrimeDelegate;
}
public void RemoveDelegate(PrimeDelegate callback) //해지
{
callbacks = Delegate.Remove(callbacks,callback) as PrimeDelegate;
}
public void Run(int limit)
{
for(int i=2; i<=limit; i++)
{
if(IsPrime(i)&& callbacks != null)
{
callbacks(i); //콜백메서드의 묶음 전부 호출
}
}
}
public bool IsPrime(int num)
{
if((num & 1) == 0)
{
return num == 2;
}
for(int i=3; (i*i)<=num; i += 2)
{
if ((num % i) == 0) return false;
}
return num != 1;
}
}
✅ 결과
발견된 소수 :2
누적된 소수의 합 : 2
발견된 소수 :3
누적된 소수의 합 : 5
발견된 소수 :5
누적된 소수의 합 : 10
발견된 소수 :7
누적된 소수의 합 : 17
====================new trial==================
발견된 소수 :2
발견된 소수 :3
발견된 소수 :5
발견된 소수 :7
발견된 소수 :11
발견된 소수 :13
이처럼 delegate로도 콜백 메서드 묶음을 정의하고, 이를 구독하거나 해지할 수도 있다. 이제 위의 코드를 event 형식에 알맞게 수정하겠다.
✍ 샘플 코드
class Test
{
static void Main(string[] args)
{
PrimeGenerator generator = new PrimeGenerator();
PrimeGenerator.PrimeDelegate callbackPrint = PrintPrime;
generator.AddDelegate(callbackPrint);
PrimeGenerator.PrimeDelegate callbackSum = SumPrime;
generator.AddDelegate(callbackSum);
generator.Run(10);
Console.WriteLine("====================new trial==================");
generator.RemoveDelegate(callbackSum);
generator.Run(15);
}
//콜백 메서드 1
static void PrintPrime(object sender, CallbackArg arg)
{
Console.WriteLine("발견된 소수 :"+arg.num);
}
static int sum;
//콜백메서드 2
static void SumPrime(object sender, CallbackArg arg)
{
sum += arg.num;
Console.WriteLine("누적된 소수의 합 : "+sum);
}
}
class CallbackArg
{
public int num;
public CallbackArg(int num)
{
this.num = num;
}
}
class PrimeGenerator
{
public delegate void PrimeDelegate(object sender, CallbackArg arg);//콜백메서드 묶음을 담을 델리게이트 선언
PrimeDelegate callbacks; //콜백메서드의 묶음
public void AddDelegate(PrimeDelegate callback) //구독
{
callbacks = Delegate.Combine(callbacks,callback) as PrimeDelegate;
}
public void RemoveDelegate(PrimeDelegate callback) //해지
{
callbacks = Delegate.Remove(callbacks,callback) as PrimeDelegate;
}
public void Run(int limit)
{
for(int i=2; i<=limit; i++)
{
if(IsPrime(i)&& callbacks != null)
{
callbacks(this, new CallbackArg(i)); //콜백메서드의 묶음 전부 호출
}
}
}
public bool IsPrime(int num)
{
if((num & 1) == 0)
{
return num == 2;
}
for(int i=3; (i*i)<=num; i += 2)
{
if ((num % i) == 0) return false;
}
return num != 1;
}
}
결과는 첫 번째 샘플 코드와 마찬가지로 나온다. 이제 이 코드를 event를 이용하여 변형하겠다.
class Test
{
static void Main(string[] args)
{
PrimeGenerator generator = new PrimeGenerator();
generator.PrimeGeneratedEvents += PrintPrime;
generator.PrimeGeneratedEvents += SumPrime;
generator.Run(10);
Console.WriteLine("====================new trial==================");
generator.PrimeGeneratedEvents -= SumPrime;
generator.Run(15);
}
//콜백 메서드 1
static void PrintPrime(object sender, EventArgs arg)
{
Console.WriteLine("발견된 소수 :"+(arg as CallbackArg).num);
}
static int sum;
//콜백메서드 2
static void SumPrime(object sender, EventArgs arg)
{
sum += (arg as CallbackArg).num;
Console.WriteLine("누적된 소수의 합 : "+sum);
}
}
class CallbackArg : EventArgs
{
public int num;
public CallbackArg(int num)
{
this.num = num;
}
}
class PrimeGenerator
{
public event EventHandler PrimeGeneratedEvents;
//EventHandler의 선언으로 델리게이트 타입의 선언과 구독, 해지를 작성하지 않아도 되게 되었다.
/* public delegate void PrimeDelegate(object sender, CallbackArg arg);//콜백메서드 묶음을 담을 델리게이트 선언
PrimeDelegate callbacks; //콜백메서드의 묶음
public void AddDelegate(PrimeDelegate callback) //구독
{
callbacks = Delegate.Combine(callbacks,callback) as PrimeDelegate;
}
public void RemoveDelegate(PrimeDelegate callback) //해지
{
callbacks = Delegate.Remove(callbacks,callback) as PrimeDelegate;
}*/
public void Run(int limit)
{
for(int i=2; i<=limit; i++)
{
if(IsPrime(i)&& PrimeGeneratedEvents != null)
{
PrimeGeneratedEvents(this, new CallbackArg(i)); //콜백메서드의 묶음 전부 호출
}
}
}
public bool IsPrime(int num)
{
if((num & 1) == 0)
{
return num == 2;
}
for(int i=3; (i*i)<=num; i += 2)
{
if ((num % i) == 0) return false;
}
return num != 1;
}
}
즉, 이벤트는 델리게이트의 사용 패턴을 좀 더 일반화해서 제공하는 것이다.
🧐 더 알아보기