해당코드는 [시작하세요! C# 6.0] 도서의 코드를 인용하였다.
위 포스팅을 참조하면 개념적으로 이해하는데 아주 도움이 된다.
Delegate 판 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
using System;
namespace Delegate
{
class CallbackArg { }
class PrimeCallbackArg : CallbackArg
{
public int Prime;
public PrimeCallbackArg(int prime)
{
this.Prime = prime;
}
}
//소수 생성기.
class PrimeGenerator
{
public delegate void PrimeDelegate(PrimeCallbackArg arg);
PrimeDelegate callbacks;
public void AddDelegate(PrimeDelegate callback)
{
callbacks += callback;
}
public void RemoveDelegate(PrimeDelegate callback)
{
callbacks -= callback;
}
public void Run(int limit)
{
for (int i = 2; i <= limit; ++i)
{
if(IsPrime(i) == true && callbacks != null)
{
callbacks(new PrimeCallbackArg(i));
}
}
}
private bool IsPrime(int candidate)
{
if((candidate & 1) == 0)
{
return candidate == 2;
}
for (int i = 3; (i * i) <= candidate; i += 2)
{
if (candidate % i == 0) return false;
}
return candidate != 1;
}
}
class Program
{
// 콜백으로 등록될 메서드 1
static void PrintPrime(PrimeCallbackArg arg)
{
Console.Write(arg.Prime + ", ");
}
static int Sum;
// 콜백으로 등록될 메서드 2
static void SumPrime(PrimeCallbackArg arg)
{
Sum += arg.Prime;
}
static void Main(string[] args)
{
PrimeGenerator gen = new PrimeGenerator();
//PrintPrime 추가
PrimeGenerator.PrimeDelegate callprint = PrintPrime;
gen.AddDelegate(callprint);
//SumPrime 추가
PrimeGenerator.PrimeDelegate callsum = SumPrime;
gen.AddDelegate(callsum);
// 1 ~ 10 까지 소수를 구하고,
gen.Run(10);
Console.WriteLine();
Console.WriteLine(Sum);
// SumPrime 콜백 메서드를 제거한 후 다시 1 ~ 15 까지 소스를 구하는 메서드 호출
gen.RemoveDelegate(callsum);
gen.Run(15);
}
}
}
|
cs |
EventHandler 판 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/* ================= delegate 대신 event 예약어를 사용한 예제 ================= */
using System;
namespace ConsoleApplication1
{
class PrimeCallbackArg : EventArgs // 콜백 값을 담는 클래스 정의
{
public int Prime;
public PrimeCallbackArg(int prime)
{
this.Prime = prime;
}
}
// 소수 생성기: 소수가 발생할 때마다 등록된 콜백 메서드를 호출
class PrimeGenerator
{
public event EventHandler PrimeGenerated;
// 주어진 수까지 루프를 돌면서 소수가 발견되면 콜백 메서드 호출
public void Run(int limit)
{
for (int i = 2; i <= limit; i++)
{
if (IsPrime(i) == true && PrimeGenerated != null)
{
// 콜백을 발생시킨 측의 인스턴스와 발견된 소수를 콜백 메서드에 전달
PrimeGenerated(this, new PrimeCallbackArg(i));
}
}
}
// 소수 판정 메서드. 이해하지 못해도 상관없음.
private bool IsPrime(int candidate)
{
if ((candidate & 1) == 0)
{
return candidate == 2;
}
for (int i = 3; (i * i) <= candidate; i += 2)
{
if ((candidate % i) == 0) return false;
}
return candidate != 1;
}
}
class Program
{
// 콜백으로 등록될 메서드 1
static void PrintPrime(object sender, EventArgs arg)
{
Console.Write((arg as PrimeCallbackArg).Prime + ", ");
}
static int Sum;
// 콜백으로 등록될 메서드 2
static void SumPrime(object sender, EventArgs arg)
{
Sum += (arg as PrimeCallbackArg).Prime;
}
static void Main(string[] args)
{
PrimeGenerator gen = new PrimeGenerator();
// PrintPrime 콜백 메서드 추가
gen.PrimeGenerated += PrintPrime;
// SumPrime 콜백 메서드 추가
gen.PrimeGenerated += SumPrime;
// 1 ~ 10까지 소수를 구하고,
gen.Run(10);
Console.WriteLine();
Console.WriteLine(Sum);
// SumPrime 콜백 메서드를 제거한 후 다시 1 ~ 15까지 소수를 구하는 메서드 호출
gen.PrimeGenerated -= SumPrime;
gen.Run(15);
}
}
}
|
cs |
1. 델리게이트 코드
우선 델리게이트 코드를 해석하면 다음과 같다.
PrimeGenerator 를 기반으로, Delegate 를 callprint 용과,
callsum 용 두개를 추가한다.
이때 Delegate 초기화에 이용되는 함수는
class Program 에 선언된 두개의 메서드 이다.
둘 다, 함수 명 그대로 [출력, 소수의 합계] 부분을 맡는다.
AddDelegate 부분은 멀티캐스트로 추가적인 메서드를 추가할 수 있다.
이제 callbacks 를 호출했을 때 '+=' 된 만큼의 메소드가 호출될 것이다.
다음으로 Main 부분에서 gen.Run(10) 메소드를 실행시킨다.
이제 소수임이 확인되고, callbacks 가 null 이 아닐경우에만
callbacks 가 실행된다
callbacks 가 실행되면,
먼저 PrimeCallbackArg (int prime) 을 통해 int Prime 을 들어온 '소수값' 으로 초기화 한다.
그 후 callbacks 내에 아까 저장된 두가지 함수가 실행되게 되는데 (new PrimeCallbackArg 를 기반으로)
우리가 등록한 두개의 메소드가 실행되게 되는 것 이다.
여기까지만 이해하면 충분하다,
이제 이벤트 에서는 어떻게 사용되는지 비교 해 보자.
2. 이벤트 코드
이벤트 코드는 Main 함수에서 살펴보면 다음과 같이 다른 점이 존재한다.
이는 EventHandler 가 어떻게 구성되어있는지 알면 이해하기 쉬운데,
그냥 '등록 과정을 간소화 시킨 Delegate' 라고 보면 된다.
Delegate 에서는 AddDelegate, RemoveDelegate 함수를 호출하여 적용시켯지만.
EventHandler 에서는 그냥 += 으로 적용시킨거다.
여.기.서
위 Delegate 코드도
callbacks 를 public 으로 바꾸고,
이런 식으로 += 으로 처리한다면 유사하게 처리할 수 있다.
EventHandler 는 근본적으로 Delegate 인데,
그냥 Delegate 를 좀 더 사용하기 쉽게 일반화 시켜놓은 녀석일 뿐이다.
즉 EventHandler(Event) 는 Delegate 의 일반화 이다.
근본적으로 다르지 않다.
끝.
'Programming > C#' 카테고리의 다른 글
[C#] C# 에서 대괄호가 가지는 의미, (사전 정의된 속성, 특성) (0) | 2021.04.03 |
---|---|
[C#] async & await 을 lamdba 에서 사용시 오류 (0) | 2021.03.19 |
[C#] IEnumerable 인터페이스 상속 및 객체 열거형 만들기 (0) | 2021.03.03 |
[C#] 형변환 [as, is] (0) | 2021.02.27 |
[C#] 인터페이스 사용 이유. (0) | 2020.12.14 |