본문 바로가기

C#

C# event

반응형

C# event

delegate 는 메서드를 가리킬 수 있는 타입의 간편 표기법.

event도 간편표기법. event를 사용하면 정형화된 콜백 패턴을 구현하려할때 코드를 줄일 수 있음.

- 조건

1. 클래스에서 이벤트(콜백)를 제공한다.

2. 외부에서 자유롭게 해당 이벤트(콜백)을 구독하거나 해지하는 것이 가능하다.

3. 외부에서 구독/해지는 가능하지만 이벤트 발생은 오직 내부에서만 가능하다.

4. 이벤트의 첫번째 인자는 이벤트를 발생시킨 타입의 인스턴스다.

5. 이벤트의 두번째 인자는 해당 이벤트에 속한 의미 있는 값이 제공된다.


꽤 까다롭다.

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp2
{
    class CallbackArg { } // 콜백값을 담는 클래스의 최상위 부모 클래스
    class PrimeCallbackArg : CallbackArg
    {
        public int Prime;
 
        public PrimeCallbackArg(int prime)
        {
            this.Prime = prime;
        }
    }
    // 소수 생성기
    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) == true && callbacks != null)
                {
                    // 콜백을 발생시킨 측의 인스턴스와 발견된 소수를 콜백메서드에 전달
                    callbacks(thisnew PrimeCallbackArg(i));
                }
            }
        }
        //소수 판정 메서드
        public bool IsPrime(int candidate)
        {
            if((candidate & 1== 0)
            {
                return candidate == 2;
            }
            for(int i=3;(i*i) <= candidate;i += 2)
            {
                if ((candidate % i) == 0return false;
            }
            return candidate != 1;
        }
    }
    class Program
    {
        //콜백으로 등록될 메서드1
        static void PrintPrime(object sender, CallbackArg arg)
        {
            Console.Write((arg as PrimeCallbackArg).Prime + ", ");
        }
        static int Sum;
        //콜백으로 등록된 메서드2
        static void SumPrime(object sender, CallbackArg arg)
        {
            Sum += (arg as PrimeCallbackArg).Prime;
        }
        static void Main(string[] args)
        {
            PrimeGenerator gen = new PrimeGenerator();
 
            //Print 콜백메서드 추가
            PrimeGenerator.PrimeDelegate callprint = PrintPrime;
            gen.AddDelegate(callprint);
            //Sum 콜백메서드 추가
            PrimeGenerator.PrimeDelegate callsum = SumPrime;
            gen.AddDelegate(callsum);
            
            // 1~10까지 소수를 구하고
            gen.Run(10);
            Console.WriteLine();
            Console.WriteLine(Sum);
 
            //Sum prime 콜백메서드 제거후 1~15사이 소수 구하는 메서드 호출
            gen.RemoveDelegate(callsum);
            gen.Run(15);
            
        }
    }
           
}
 


[Delegate만을 이용한 콜백/ 소수생성기를 구현해서 1부터 n까지 값을 증가시키며 소수라고 판정할 때마다 콜백을 발생시키는 클래스]

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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp2
{
    // 부모클래스는 사라지고 닷넷에서 제공하는 System.EventArgs라는 타입 사용
    class PrimeCallbackArg : EventArgs
    {
        public int Prime;
 
        public PrimeCallbackArg(int prime)
        {
            this.Prime = prime;
        }
    }
    // 소수 생성기
    class PrimeGenerator
    {
        //기존의 AddDelegate, RemoveDelegate,PrimeDelegate는 없어짐.
        public event EventHandler PrimeGenerated;
        
        // 주어진 수까지 루프를 돌면서 소수가 발견되면 콜백메서드 호출 ****
        public void Run(int limit)
        {
            for(int i = 2; i <= limit; i++)
            {
                if(IsPrime(i) == true && PrimeGenerated != null)
                {
                    // 콜백을 발생시킨 측의 인스턴스와 발견된 소수를 콜백메서드에 전달
                    PrimeGenerated(thisnew PrimeCallbackArg(i));
                }
            }
        }
        //소수 판정 메서드
        public bool IsPrime(int candidate)
        {
            if((candidate & 1== 0)
            {
                return candidate == 2;
            }
            for(int i=3;(i*i) <= candidate;i += 2)
            {
                if ((candidate % i) == 0return 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();
 
            gen.PrimeGenerated += PrintPrime;
            gen.PrimeGenerated += SumPrime;
            
            // 1~10까지 소수를 구하고
            gen.Run(10);
            Console.WriteLine();
            Console.WriteLine(Sum);
 
            //Sum prime 콜백메서드 제거후 1~15사이 소수 구하는 메서드 호출
            gen.PrimeGenerated -= SumPrime;
            gen.Run(15);
            
        }
    }
           
}
 



[event를 이용한 콜백 구현]

결과적으로 이벤트는 delegate의 사용 패턴을 좀더 일반화, 단순화해서 제공하는 것으로

조건이 맞았을 때 코드가 간결해지는 효과를 볼 수 있다.

보통 GUI를 제공하는 응용프로그램에서 사용된다.

예를들어 버튼이 있고 버튼을 눌렀을 때 파일을 생성한다면, 버튼클래스의 제작자는 당연히 클릭이벤트를 구현해 둘 것이고 버튼을 이용하는 개발자는 클릭이벤트를 구독하는 메서드 내에서 파일 작업을 수행하는 코드를 작성할 것이다.

반응형