C# ) C# 기초 5 (대리자, 이벤트)
대리자
C#에서는 콜백을 맡아 실행하는 일을 '대리자'가 담당합니다. 대리자(Delegate)는 다른 말로 '대리인' 또는 '사절'이라고 할 수 있습니다. 즉, 누군가를 대신해서 일해주는것을 전문으로 하는 사람을 의미합니다.
** 대리자는 메서드에 대한 참조입니다.
** 대리자에 메서드의 주소를 할당한 후 대리자를 호출하면 이 대리자가 메서드를 호출해줍니다.
** Delegate는 메서드를 가리키는 참조 변수
한정자 delegate 반환_형식 대리자_이름(매개변수_목록);
delegate int MyDelegate(int a, int b);
대리자는 인스턴스(객체)가 아닌 형식(Type)입니다. 다시말해 MyDelegate는 int, string과 같은 형식이며 '메서드를 참조하는 그 무엇'을 만들려면 MyDelegate의 인스턴스를 따로 만들어야 합니다.
[대리자가 참조할 메서드 선언]
이 메서드들의 반환 형식과 매개변수는 대리자의 반환 형식과 매개변수를 따라야 합니다.
delegate int MyDelegate(int a, int b);
int Plus(int a, int b)
{
return a + b;
}
int Minus(int a, int b)
{
return a - b;
}
Plus()와 Minus() 메서드 모두 MyDelegate 대리자의 반환형식과 매개변수를 따르고 있습니다.
그럼 이 메서드를 MyDelegate가 참조할 때
MyDelegate Callback;
Callback = new MyDelegate(Plus);
// 대리자의 인스턴스를 만들 때도 new연산자 사용
Console.WriteLine(Callback(3,4)); // 7출력
Callback = new MyDelegate(Minus);
Console.WriteLine(Callback(7,5)); // 2출력
대리자를 이용하여 콜백 구현과정
1. 대리자를 선언한다.
2. 대리자의 인스턴스를 생성한다. 인스턴스를 생성할 때는 대리자가 참조할 메서드를 인수로 넘긴다.
3. 대리자를 호출한다.
using System;
namespace Delegate
{
// 대리자의 선언
delegate int MyDelegate(int a, int b);
class Calculator
{
public int Plus(int a, int b) // 대리자는 인스턴스 메서드도 참조할 수 있고
{
return a + b;
}
public static int Minus(int a, int b) // 대리자는 정적 메서드도 참조할 수 있습니다.
{
return a - b;
}
class MainApp
{
static void Main(string[] args)
{
Calculator Calc = new Calculator();
MyDelegate Callback;
Callback = new MyDelegate(Calc.Plus);
// 메서드를 호출하듯 대리자를 사용하면, 참조하고 있는 메서드가 실행됩니다.
Console.WriteLine(Callback(3, 4));
Callback = new MyDelegate(Calculator.Minus);
Console.WriteLine(Callback(7, 5));
}
}
}
}
[ 대리자를 사용하는 이유 ]
- 유연성: Delegate를 사용하면 프로그램의 동작을 실행 시점에 변경할 수 있습니다. 마치 감독이 촬영 중에 배우의 연기를 바꾸는 것처럼요!
- 재사용성: Delegate를 사용하면 동일한 코드를 여러 곳에서 재사용할 수 있습니다. 마치 감독이 같은 배우에게 여러 장면에서 연기를 시키는 것과 같죠!
- 이벤트 처리: Delegate는 이벤트 처리에 필수적인 요소입니다. 마치 감독이 "큐!" 사인을 주면 배우가 연기를 시작하는 것처럼, 특정 이벤트가 발생하면 Delegate를 통해 연결된 메서드가 실행됩니다.
** Delegate를 사용하면 코드가 더욱 유연하고 재사용 가능하며, 이벤트 처리를 효율적으로 구현할 수 있다
버튼을 클릭했을 때 특정 작업을 수행하는 프로그램을 생각해 봅시다. Delegate를 사용하지 않으면 버튼 클릭 이벤트가 발생할 때마다 동일한 작업만 수행할 수 있습니다. 하지만 Delegate를 사용하면 버튼 클릭 이벤트에 연결되는 메서드를 변경하여, 버튼 클릭 시 실행되는 작업을 다양하게 바꿀 수 있습니다.
예를 들어, "계산기" 프로그램에서 Delegate를 사용하면 덧셈 버튼을 클릭했을 때 덧셈을 수행하는 메서드를 실행하고, 뺄셈 버튼을 클릭했을 때 뺄셈을 수행하는 메서드를 실행하도록 할 수 있습니다.
사용 예시
비교 메서드를 참조할 대리자를 매개변수에 받을 수 있도록 정렬 메서드를 작성
1. Compare 대리자를 선언
delegate int Compare(int a, int b);
2. Compare 대리자가 참조할 비교 메서드를 작성
static int AscendCompare(int a, int b)
{
if(a > b)
{
return 1;
}
else if( a == b)
{
return 0;
}
else
{
return -1;
}
}
3. 정렬 메서드를 작성 하고 이 때 매개변수로는 정렬할 배열과 비교할 메서드를 참조하는 대리자를 입력받는다.
static void BubbleSort(int[] DataSet, Compare Comparer)
{
int i = 0;
int j = 0;
int temp = 0;
for(i = 0; i < DataSet.Length-1; i++)
{
if(Comparer(DataSet[j], DataSet[j+1] > 0)
// Comparer가 어떤 메서드를 참조하고 있는가에 따라 정렬 결과가 달라집니다.
{
temp = DataSet[j+1];
DataSet[j+1] = DataSet[j];
DataSet[j] = temp;
}
}
}
4. 정렬 메서들 호출하면 우리가 원하던 대로 정렬 방식이 분리된 정렬 코드를 얻을 수 있습니다. 지금까지 입력한 코드는 오름차순 정렬 코드입니다. Comparer가 참조할 메서드를 새로 구현해서 내림차순으로 정렬한다면 BubbleSort를 호출할 때 매개변수로 메서드를 넘기면 됩니다.
int[] array = {3, 7, 4, 2, 10};
BubbleSort(array, new Compare(AscendCompare)); // array는 {2,3,4,7,10}
using System;
namespace UsingCallback
{
delegate int Compare(int a, int b); // 델리게이트 선언: Compare라는 이름의 델리게이트를 선언합니다. 이 델리게이트는 두 개의 정수를 입력으로 받아 정수 값을 반환하는 메서드를 참조할 수 있습니다. 마치 "두 숫자를 비교하는 방법"을 정의하는 계약서와 같아요.
class MainApp // 클래스 선언: MainApp이라는 이름의 클래스를 정의합니다.
{
static int AscendCompare(int a, int b) // 메서드 정의: AscendCompare 메서드는 두 개의 정수를 입력으로 받아 오름차순으로 비교한 결과를 반환합니다. a가 b보다 크면 1, 같으면 0, 작으면 -1을 반환합니다.
{
if (a > b)
{
return 1;
}
else if (a == b)
{
return 0;
}
else
{
return -1;
}
}
static int DescendCompare(int a, int b) // 메서드 정의: DescendCompare 메서드는 두 개의 정수를 입력으로 받아 내림차순으로 비교한 결과를 반환합니다. a가 b보다 작으면 1, 같으면 0, 크면 -1을 반환합니다.
{
if (a < b)
{
return 1;
}
else if (a == b)
{
return 0;
}
else
{
return -1;
}
}
static void BubbleSort(int[] DataSet, Compare Comparer) // 메서드 정의: BubbleSort 메서드는 정수 배열과 Compare 델리게이트를 입력으로 받아 버블 정렬을 수행합니다.
{
int i = 0;
int j = 0;
int temp = 0;
for (i = 0; i < DataSet.Length - 1; i++) // 바깥쪽 반복문: 배열의 길이만큼 반복합니다.
{
for (j = 0; j < DataSet.Length - (i + 1); j++) // 안쪽 반복문: 배열의 길이에서 i+1을 뺀 만큼 반복합니다.
{
if (Comparer(DataSet[j], DataSet[j + 1]) > 0) // Compare 델리게이트를 사용하여 현재 요소와 다음 요소를 비교합니다. 비교 결과가 0보다 크면 두 요소의 위치를 바꿉니다.
{
temp = DataSet[j + 1];
DataSet[j + 1] = DataSet[j];
DataSet[j] = temp;
}
}
}
}
static void Main(string[] args) // 메서드 정의: 프로그램의 진입점인 Main 메서드입니다.
{
int[] array = { 3, 7, 4, 2, 10 }; // 정수 배열 선언 및 초기화: array 변수에 정수 배열을 할당합니다.
Console.WriteLine("Sorting ascending..."); // 콘솔 출력: "Sorting ascending..." 메시지를 출력합니다.
BubbleSort(array, new Compare(AscendCompare)); // BubbleSort 메서드 호출: array 배열을 AscendCompare 메서드를 사용하여 오름차순으로 정렬합니다.
for (int i = 0; i < array.Length; i++) // 반복문: 정렬된 배열을 출력합니다.
{
Console.Write($"{array[i]}");
}
int[] array2 = { 7, 2, 8, 10, 11 }; // 정수 배열 선언 및 초기화: array2 변수에 정수 배열을 할당합니다.
Console.WriteLine("\nSorting descending..."); // 콘솔 출력: "Sorting descending..." 메시지를 출력합니다.
BubbleSort(array2, new Compare(DescendCompare)); // BubbleSort 메서드 호출: array2 배열을 DescendCompare 메서드를 사용하여 내림차순으로 정렬합니다.
for (int i = 0; i < array2.Length; i++) // 반복문: 정렬된 배열을 출력합니다.
{
Console.Write($"{array2[i]}");
}
Console.WriteLine(); // 콘솔 출력: 줄 바꿈을 합니다.
}
}
}
일반화 대리자
일반화 메서드를 참조할 수 있도록 형식 매개변수를 이용하여 선언되어야 합니다.
delegate int Compare<T>(T a, T b);
using System;
namespace GenericDelegate
{
delegate int Compare<T>(T a, T b); // Compare<T>라는 제네릭 델리게이트를 선언합니다. 이 델리게이트는 두 개의 형식 매개변수 T를 입력으로 받아 정수 값을 반환하는 메서드를 참조할 수 있습니다. 즉, 다양한 형식의 데이터를 비교하는 메서드를 나타낼 수 있습니다.
class MainApp // MainApp이라는 이름의 클래스를 선언합니다.
{
static int AscendCompare<T>(T a, T b) where T : IComparable<T> // AscendCompare<T>라는 제네릭 메서드를 정의합니다. 이 메서드는 두 개의 형식 매개변수 T를 입력으로 받아 오름차순으로 비교한 결과를 반환합니다. where T : IComparable<T> 제약 조건은 T가 IComparable<T> 인터페이스를 구현해야 함을 의미합니다. 즉, T는 비교 가능한 형식이어야 합니다.
{
return a.CompareTo(b); // a.CompareTo(b)는 a와 b를 비교하여 a가 b보다 작으면 -1, 같으면 0, 크면 1을 반환합니다.
}
static int DescendCompare<T>(T a, T b) where T : IComparable<T> // DescendCompare<T>라는 제네릭 메서드를 정의합니다. 이 메서드는 두 개의 형식 매개변수 T를 입력으로 받아 내림차순으로 비교한 결과를 반환합니다. where T : IComparable<T> 제약 조건은 T가 IComparable<T> 인터페이스를 구현해야 함을 의미합니다. 즉, T는 비교 가능한 형식이어야 합니다.
{
return a.CompareTo(b) * -1; // a.CompareTo(b)의 결과에 -1을 곱하여 내림차순 비교 결과를 반환합니다.
}
static void BubbleSort<T>(T[] DataSet, Compare<T> Comparer) // BubbleSort<T>라는 제네릭 메서드를 정의합니다. 이 메서드는 형식 매개변수 T의 배열과 Compare<T> 델리게이트를 입력으로 받아 버블 정렬을 수행합니다.
{
int i = 0; // 반복문에 사용할 변수 i를 선언하고 0으로 초기화합니다.
int j = 0; // 반복문에 사용할 변수 j를 선언하고 0으로 초기화합니다.
T temp; // 임시 변수 temp를 선언합니다.
for (i = 0; i < DataSet.Length - 1; i++) // 바깥쪽 반복문: 배열의 길이만큼 반복합니다.
{
for (j = 0; j < DataSet.Length - (i + 1); j++) // 안쪽 반복문: 배열의 길이에서 i+1을 뺀 만큼 반복합니다.
{
if (Comparer(DataSet[j], DataSet[j + 1]) > 0) // Compare<T> 델리게이트를 사용하여 현재 요소와 다음 요소를 비교합니다. 비교 결과가 0보다 크면 두 요소의 위치를 바꿉니다.
{
temp = DataSet[j + 1]; // 다음 요소를 temp에 저장합니다.
DataSet[j + 1] = DataSet[j]; // 현재 요소를 다음 요소 위치에 저장합니다.
DataSet[j] = temp; // temp에 저장된 다음 요소를 현재 요소 위치에 저장합니다.
}
}
}
}
static void Main(string[] args) // 프로그램의 진입점인 Main 메서드입니다.
{
int[] array = { 3, 7, 4, 2, 10 }; // 정수 배열 array를 선언하고 초기화합니다.
Console.WriteLine("Sorting ascending..."); // 콘솔에 "Sorting ascending..." 메시지를 출력합니다.
BubbleSort<int>(array, new Compare<int>(AscendCompare)); // BubbleSort<int> 메서드를 호출하여 array 배열을 AscendCompare<int> 메서드를 사용하여 오름차순으로 정렬합니다.
for (int i = 0; i < array.Length; i++) // 반복문: 정렬된 배열을 출력합니다.
Console.Write($"{array[i]} "); // 배열의 각 요소를 콘솔에 출력합니다.
string[] array2 = { "abc", "def", "ghi", "jkl", "mno" }; // 문자열 배열 array2를 선언하고 초기화합니다.
Console.WriteLine("\nSorting descending..."); // 콘솔에 "Sorting descending..." 메시지를 출력합니다.
BubbleSort<string>(array2, new Compare<string>(DescendCompare)); // BubbleSort<string> 메서드를 호출하여 array2 배열을 DescendCompare<string> 메서드를 사용하여 내림차순으로 정렬합니다.
for (int i = 0; i < array2.Length; i++) // 반복문: 정렬된 배열을 출력합니다.
Console.Write($"{array2[i]} "); // 배열의 각 요소를 콘솔에 출력합니다.
Console.WriteLine(); // 콘솔에 줄 바꿈을 합니다.
}
}
}
대리자 체인
대리자 하나가 메서드 여러 개를 동시에 참조할 수 있다.
** 대리자 체인은 이 메서드들을 연결하여 순차적으로 실행하는 것을 의미
대리자 체인은 여러 개의 델리게이트를 하나로 묶어서 호출하는 것을 말합니다. 즉, 하나의 델리게이트에 여러 메서드를 연결하여 마치 하나의 메서드처럼 호출
대리자 체인을 사용하면 여러 메서드를 순차적으로 실행해야 하는 경우 코드를 간결하게 작성할 수 있고, 프로그램의 유연성을 높일 수 있습니다. 마치 여러 사람이 힘을 합쳐서 일을 하는 것처럼, 여러 메서드가 협력하여 작업을 수행
using System;
namespace DelegateChains
{
// Notify라는 이름의 델리게이트를 선언합니다.
// 이 델리게이트는 문자열을 매개변수로 받아 void를 반환하는 메서드를 나타냅니다.
delegate void Notify(string message);
class Notifier
{
public Notify EventOccured; // Notify 델리게이트 형식의 EventOccured 이벤트를 선언합니다. 이 이벤트는 무언가 발생했을 때 알림을 보내는 데 사용됩니다.
}
class EventListener
{
private string name; // 이벤트 리스너의 이름을 저장하는 private 필드입니다.
public EventListener(string name) // EventListener 클래스의 생성자입니다. 이벤트 리스너의 이름을 초기화합니다.
{
this.name = name;
}
public void SomethingHappend(string message) // SomethingHappend라는 이름의 메서드를 정의합니다. 이 메서드는 이벤트가 발생했을 때 수행할 작업을 정의합니다.
{
Console.WriteLine($"{name}.SomethingHappened : {message}"); // 콘솔에 이벤트 리스너의 이름과 메시지를 출력합니다.
}
}
class MainApp
{
static void Main(string[] args) // 프로그램의 진입점인 Main 메서드입니다.
{
Notifier notifier = new Notifier(); // Notifier 클래스의 인스턴스를 생성합니다.
EventListener listener1 = new EventListener("Listener1"); // EventListener 클래스의 인스턴스를 생성합니다.
EventListener listener2 = new EventListener("Listener2"); // EventListener 클래스의 인스턴스를 생성합니다.
EventListener listener3 = new EventListener("Listener3"); // EventListener 클래스의 인스턴스를 생성합니다.
notifier.EventOccured += listener1.SomethingHappend; // listener1의 SomethingHappend 메서드를 notifier의 EventOccured 이벤트에 추가합니다.
notifier.EventOccured += listener2.SomethingHappend; // listener2의 SomethingHappend 메서드를 notifier의 EventOccured 이벤트에 추가합니다.
notifier.EventOccured += listener3.SomethingHappend; // listener3의 SomethingHappend 메서드를 notifier의 EventOccured 이벤트에 추가합니다.
notifier.EventOccured("You've got mail."); // EventOccured 이벤트를 발생시킵니다. "You've got mail." 메시지를 전달합니다.
Console.WriteLine(); // 콘솔에 빈 줄을 출력합니다.
notifier.EventOccured -= listener2.SomethingHappend; // listener2의 SomethingHappend 메서드를 notifier의 EventOccured 이벤트에서 제거합니다.
notifier.EventOccured("Download complete."); // EventOccured 이벤트를 발생시킵니다. "Download complete." 메시지를 전달합니다.
Console.WriteLine(); // 콘솔에 빈 줄을 출력합니다.
notifier.EventOccured = new Notify(listener2.SomethingHappend) // notifier의 EventOccured 이벤트를 listener2의 SomethingHappend 메서드와 listener3의 SomethingHappend 메서드로 설정합니다.
+ new Notify(listener3.SomethingHappend);
notifier.EventOccured("Nuclear launch detected."); // EventOccured 이벤트를 발생시킵니다. "Nuclear launch detected." 메시지를 전달합니다.
Console.WriteLine(); // 콘솔에 빈 줄을 출력합니다.
Notify notify1 = new Notify(listener1.SomethingHappend); // listener1의 SomethingHappend 메서드를 나타내는 Notify 델리게이트를 생성합니다.
Notify notify2 = new Notify(listener2.SomethingHappend); // listener2의 SomethingHappend 메서드를 나타내는 Notify 델리게이트를 생성합니다.
notifier.EventOccured =
(Notify)Delegate.Combine(notify1, notify2); // Delegate.Combine 메서드를 사용하여 notify1과 notify2를 결합하고 notifier의 EventOccured 이벤트에 할당합니다.
notifier.EventOccured("Fire!!"); // EventOccured 이벤트를 발생시킵니다. "Fire!!" 메시지를 전달합니다.
Console.WriteLine(); // 콘솔에 빈 줄을 출력합니다.
notifier.EventOccured =
(Notify)Delegate.Remove(notifier.EventOccured, notify2); // Delegate.Remove 메서드를 사용하여 notifier의 EventOccured 이벤트에서 notify2를 제거합니다.
notifier.EventOccured("RPG!"); // EventOccured 이벤트를 발생시킵니다. "RPG!" 메시지를 전달합니다.
}
}
}
- 델리게이트: 메서드를 참조하는 형식입니다.
- 델리게이트 체인: 여러 델리게이트를 하나로 묶어서 호출하는 것.
- 이벤트: 특정 상황이 발생했을 때 알림을 보내는 메커니즘.
=> notifier.EventOccured += listener1.SomethingHappend;와 같이 += 연산자를 사용하여 listener1, listener2, listener3의 SomethingHappend 메서드를 notifier의 EventOccured 이벤트에 추가
=> notifier.EventOccured("You've got mail.");과 같이 EventOccured 이벤트를 발생시키면 체인에 추가된 모든 메서드가 순차적으로 실행됩니다.
=> -= 연산자를 사용하여 이벤트에서 메서드를 제거할 수도 있습니다.
=> Delegate.Combine 메서드를 사용하여 여러 델리게이트를 하나의 델리게이트로 결합할 수 있습니다.
=> Delegate.Remove 메서드를 사용하여 델리게이트에서 특정 메서드를 제거할 수 있습니다.
익명 메서드
메서드는 보통 다음과 같이 선언됩니다. 한정자가 없어도, 반환할 값이 없어도(void), 매개변수가 없어도 괜찮지만 이름만은 있어야 합니다.
void DoSomething()
{
}
익명 메소드 란 이름이 없는 메서드를 말합니다.
대리자_인스턴스 = delegate (매개변수_목록)
{
//실행하려는 코드 ...
};
익명 메서드를 사용하는 이유
- 간결한 코드: 짧은 코드를 작성할 때 메서드 이름을 짓는 것이 번거로울 수 있습니다. 익명 메서드를 사용하면 메서드 이름을 생략하여 코드를 간결하게 만들 수 있습니다.
- 일회성 사용: 한 번만 사용하는 메서드를 위해 이름을 짓는 것은 불필요합니다. 익명 메서드는 이러한 경우에 유용하게 사용될 수 있습니다.
- 델리게이트와 함께 사용: 익명 메서드는 델리게이트와 함께 사용될 때 매우 유용합니다. 델리게이트는 메서드를 참조하는 변수인데, 익명 메서드를 사용하면 델리게이트에 직접 코드를 할당할 수 있습니다.
delegate int Calculate(int a, int b);
static void Main(string[] args)
{
// 익명 메서드를 사용하여 델리게이트 인스턴스 생성
Calculate calc = delegate(int a, int b) { return a + b; };
// 델리게이트 호출
int result = calc(3, 4);
Console.WriteLine(result); // 출력: 7
}
=> 이 코드에서는 Calculate 델리게이트에 익명 메서드를 할당하여 두 수를 더하는 기능을 구현했습니다. 익명 메서드는 delegate(int a, int b) { return a + b; } 부분이며, 이름 없이 바로 코드 블록을 작성한 것을 볼 수 있습니다.
using System;
using System.Windows.Forms;
public class MainForm : Form
{
private Button button1;
public MainForm()
{
button1 = new Button();
button1.Text = "Click Me!";
button1.Click += delegate(object sender, EventArgs e) // 익명의 메서드
{
MessageBox.Show("Button clicked!");
};
Controls.Add(button1);
}
static void Main()
{
Application.Run(new MainForm());
}
}
=> 이 코드에서는 버튼 클릭 이벤트 처리기에 익명 메서드를 사용했습니다. button1.Click += delegate(object sender, EventArgs e) { MessageBox.Show("Button clicked!"); }; 부분에서 익명 메서드를 통해 버튼 클릭 시 메시지 박스를 표시하는 기능을 구현했습니다.
이벤트
** C# 이벤트는 특정 사건이 발생했을 때 다른 객체에게 알리는 메커니즘입니다.
이벤트를 선언하고 사용하는 절차
1. 대리자를 선언합니다. 이 대리자는 클래스 밖에 선언해도 되고 안에 선언해도 됩니다.
2. 클래스 내에 1번에서 선언한 대리자의 인스턴스 event 한정자로 수식해서 선언합니다.
3. 이벤트 핸들러를 작성합니다. 이벤트 핸들러는 1번에서 선언한 대리자와 일치하는 메서드면 됩니다.
4. 클래스의 인스턴스를 생성하고 이 객체의 이벤트에 3번에서 작성한 이벤트 핸들러를 등록합니다.
5. 이벤트가 발생하면 이벤트 핸들러가 호출됩니다.
1. 대리자를 선언합니다. (이 대리자는 클래스 밖에 선언해도 되고 안에 선언해도 됩니다.)
delegate void EventHandler(string message);
2. 클래스 내에 1번에서 선언한 대리자의 인스턴스를 event 한정자로 수식해서 선언합니다.
class MyNotifier
{
public event EventHandler SomethingHappend;
// EventHandler는 1번에서 선언한 대리자입니다.
public void DoSomething(int number)
{
int temp = number % 10;
if(temp != 0 && temp % 3 == 0)
{
SomethingHappend(String.Format("{0}: 짝", number));
}
}
}
3. 이벤트 핸들러를 작성합니다. 이벤트 핸들러는 1번에서 선언한 대리자와 일치하는 메서드면 됩니다.
class MainApp
{
static public void MyHandler(string message)
// SomethingHappend 이벤트에서 사용할 이벤트 핸들러(MyHandler)는 EventHandler대리자의 형식과 동일한 메서드여야 합니다.
{
Console.WriteLine(message);
}
}
4. 클래스의 인스턴스를 생성하고 이 객체의 이벤트에 3번에서 작성한 이벤트 핸들러를 등록합니다.
class MainApp
{
static public void MyHandler(string message)
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
MyNotifier notifier = new MyNotifier();
notifier.SomethingHappend += new EventHandler(MyHandler);
// SomethingHappend 이벤트에 MyHandler() 메서드를 이벤트에
// MyHandler()메서드를 이벤트 핸들러로 등록합니다.
for(int i = 1; i < 30; i++)
{
notifier.DoSomething(i);
}
}
}
5. 이벤트가 발생하면 이벤트 핸들러가 호출됩니다.
class MainApp
{
static public void MyHandler(string message)
{
Console.WriteLine(message);
}
static void Main(string[] args)
{
MyNotifier notifier = new MyNotifier();
notifier.SomethingHappened += MyHandler;
// += 연산자를 사용하여 이벤트 처리기를 이벤트에 등록한다.
for(int i = 0; i < 30; i++)
{
notifier.DoSomething(i);
}
}
}
이벤트의 주요 구성 요소
- 이벤트 발생자 (Publisher): 이벤트를 발생시키는 객체입니다. 알람 시계 예시에서는 알람 시계 자체가 이벤트 발생자입니다.
- 이벤트 처리기 (Subscriber): 이벤트가 발생했을 때 호출되는 메서드입니다. 알람 시계 예시에서는 사용자가 깨어나는 행동이 이벤트 처리기입니다.
- 이벤트 핸들러 (Event Handler): 이벤트 처리기를 포함하는 델리게이트입니다. 이벤트 발생자와 이벤트 처리기를 연결하는 역할을 합니다.
이벤트와 델리게이트
C# 이벤트는 델리게이트를 기반으로 구현됩니다. 델리게이트는 메서드를 참조하는 형식으로, 이벤트 핸들러는 특정 형식의 델리게이트를 사용합니다.