C#
대리자와 이벤트
윤태영(Coding)
2023. 6. 17. 20:54
< 대리자(Delegate) 란? >
대리자는 메서드를 가리키는 타입이다. 그래서 대리자를 통해 메서드를 호출할 수 있다.
병사가 장교에게 전화를 했는데, 장교가 아닌 다른 부사관이 받아서, 부사관이 장교에게 ~사항을 전해달라고 부탁 해서, 그 부사관이 장교에게 전달 사항을 주면, 장교가 다시 병사에게 가서, 전달 사항에 대해 처리를 해주는 상황과 비슷하다.
예를 들어, "더하기"라는 메서드를 호출하고 싶다면, 대리자를 사용해서 "더하기" 메서드를 가리키고, 대리자를 통해 그 메서드를 실행할 수 있다.
< 대리자 선언, 사용하기 >
ConsoleApp 프로젝트를 만들어서 대리자 선언 및 사용하는 코드
using System;
namespace DelegatesExample
{
class Program
{
// 대리자를 선언한다. 이 대리자는 두 정수를 받아서, 정수를 반환하는 메서드를 참조할 수 있다.
public delegate int Calculate(int x, int y);
// 대리자가 참조할 수 있는 형태의 메서드를 만든다.
public static int Add(int a, int b)
{
return a + b;
}
static void Main(string[] args)
{
// 대리자 인스턴스를 생성하고, Add 메서드를 참조하도록 한다.
Calculate calculate = Add;
// 대리자 인스턴스를 통해 Add 메서드를 호출한다.
int result = calculate(3, 4);
Console.WriteLine($"3 + 4 = {result}");
}
}
}
코드를 실행하면, 아래와 같이, 정상적으로 작동된다.
[일반화 된 대리자 사용하기 ]
Func와 Action은 C#에서 기본적으로 제공하는 일반화된 대리자다. Func는 반환값이 있는 메서드를, Action은 반환값이 없는 메서드를 참조한다.
using System;
namespace DelegatesExample
{
class Program
{
// 대리자를 선언한다. 이 대리자는 두 정수를 받아서, 정수를 반환하는 메서드를 참조할 수 있다.
public delegate string Calculate(int x, string y);
// 대리자가 참조할 수 있는 형태의 메서드를 만든다.
public static string Add(int a, string b)
{
return $"{a} + {b}";
}
static void Main(string[] args)
{
// Func 대리자를 사용하는 예시
Func<int, string, string> addFunc = Add;
string resultFunc = addFunc(5, "감자");
Console.WriteLine($"5 + 감자 = {resultFunc}");
// 사용자 정의 대리자를 사용하는 예시
Calculate calculate = Add;
string resultCalculate = calculate(5, "감자");
Console.WriteLine($"5 + 감자 = {resultCalculate}");
}
}
}
using System;
namespace DelegatesExample
{
class Program
{
delegate void MyDelegate(string message);
static void Main()
{
Action<string> myAction = SayHello;
myAction("Hello with Action!");
Func<int, int, int> myFunc = Sum;
int result = myFunc(3, 4);
Console.WriteLine("Sum with Func: " + result);
}
static void SayHello(string message)
{
Console.WriteLine(message);
}
static int Sum(int a, int b)
{
return a + b;
}
}
}
< 대리자 체인 >
여러 메서드를 하나의 대리자에 연결하여 한 번에 호출할 수 있다. 이를 대리자 체인이라고 한다.
using System;
namespace DelegatesExample
{
class Program
{
delegate void MyDelegate(string message);
static void Main()
{
Action<string> myAction = SayHello;
myAction += SayGoodbye;
myAction("태영님");
}
static void SayHello(string name)
{
Console.WriteLine($"안녕하세요, {name}!");
}
static void SayGoodbye(string name)
{
Console.WriteLine($"조심히 가십시오, {name}!");
}
}
}
< 익명 메서드 >
대리자에 이름이 없는 메서드를 직접 할당할 수도 있다.
using System;
namespace DelegatesExample
{
class Program
{
delegate void MyDelegate(string message);
static void Main()
{
Action<string> myAction = delegate (string message)
{
Console.WriteLine(message);
};
myAction("반갑습니다!!!");
}
}
}
< 이벤트 >
이벤트(Events)
이벤트는 어떤 사건이 발생했을 때 해당 사건을 처리하는 메서드를 실행하는 데 사용된다. 이벤트를 선언할 때는 event 키워드를 사용한다.
.NET Core 또는 .NET 5~6 프로젝트를 만들어서
Program.cs에 아래와 같이 코드를 작성하고 실행해보면, Button 클릭 확인 문구가 출력되는걸 볼 수 있다.
이 Event 키워드와, 대리자를 사용해서
using System;
namespace EventExample
{
public class Alarm
{
// 대리자 타입 선언
public delegate void AlarmEventHandler(string message);
// 이벤트 선언
public event AlarmEventHandler AlarmEvent;
// 메서드를 호출하여 알람 이벤트를 발생
public void RaiseAlarm(string message)
{
// 이벤트가 null이 아닌 경우에만 이벤트를 발생시키기
AlarmEvent?.Invoke(message);
}
}
class Program
{
static void Main()
{
// Alarm 클래스의 인스턴스를 생성
Alarm alarm = new Alarm();
// 알람 이벤트에 대한 처리 로직을 익명 메서드로 등록
alarm.AlarmEvent += delegate (string message)
{
Console.WriteLine($"알람: {message}");
};
// 알람 이벤트 발생
alarm.RaiseAlarm("불이야!");
}
}
}
이렇게 작성도 가능하다.