반응형
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(this, new 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) == 0) return 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(this, new 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) == 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(); 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를 제공하는 응용프로그램에서 사용된다.
예를들어 버튼이 있고 버튼을 눌렀을 때 파일을 생성한다면, 버튼클래스의 제작자는 당연히 클릭이벤트를 구현해 둘 것이고 버튼을 이용하는 개발자는 클릭이벤트를 구독하는 메서드 내에서 파일 작업을 수행하는 코드를 작성할 것이다.
반응형
'C#' 카테고리의 다른 글
C# 구조체, ref, out (6) | 2017.09.18 |
---|---|
C# 인터페이스 (2) | 2017.09.17 |
C# delegate (콜백, 체인, 범용성) (0) | 2017.09.16 |
C# 다형성 (override, overload, implicit, explicit) (0) | 2017.09.15 |
C# 캡슐화, 상속(접근제한자, 프로퍼티, as, is, Object, this, base) (0) | 2017.09.15 |