목차
C#의 이벤트 처리 방식
유니티 C#에서는 여러 가지 함수들을 하나의 변수에 저장한 뒤, 처리하는 이벤트 처리 방식이 있습니다.
이러한 기능을 구현하기 위해 주로 사용되는 것은 Delegate입니다. Delegate는 메서드 참조를 위한 타입으로, 한 개 이상의 메서드를 참조할 수 있습니다. 이를 통해 다양한 함수를 하나의 델리게이트 변수에 저장하여 관리할 수 있으며, 필요한 시점에 호출할 수 있습니다.
Delegate
Delegate는 하나 이상의 메서드를 참조할 수 있는 타입입니다.
델리게이트를 사용하면 메서드를 변수에 할당하고, 다른 메서드로 전달하거나, 다른 객체의 메서드를 호출할 수 있습니다
Delegate의 선언과 사용
public delegate int Operation(int x, int y);
public int Add(int x, int y) {
return x + y;
}
public int Multiply(int x, int y) {
return x * y;
}
Operation op = new Operation(Add);
int result = op(5, 3); // 결과는 8
op = Multiply;
result = op(5, 3); // 결과는 15
C#
복사
event
event 키워드는 특별한 유형의 델리게이트입니다.
이 키워드를 사용하여 클래스나 구조체에서 특정 상황이 발생했을 때 이를 알리는 이벤트를 정의할 수 있습니다.
이벤트는 클래스의 인터페이스의 일부로, 클래스 외부에서 이벤트 핸들러를 추가하거나 제거할 수 있도록 하지만, 이벤트를 직접 발생시킬 수는 없습니다.
event 키워드의 기능
•
캡슐화 : 이벤트는 클래스 외부에서 이벤트를 직접 발생시킬 수 없게 하여, 클래스의 책임과 기능을 명확히 분리합니다.
•
구독 관리 : 클래스 외부의 코드는 이벤트에 대해 구독(+=)하거나 구독 취소(=)할 수 있으나, 이벤트 리스트를 직접 수정할 수는 없습니다. 이를 통해 클래스의 내부 구현을 숨기고 오용을 방지할 수 있습니다.
public delegate void HealthChangedHandler(int newHealth);
public class Player
{
public event HealthChangedHandler HealthChanged;
private int health;
public int Health
{
get { return health; }
set
{
if (health != value)
{
health = value;
OnHealthChanged(health);
}
}
}
protected virtual void OnHealthChanged(int newHealth)
{
HealthChanged?.Invoke(newHealth);
}
}
public static void Main()
{
Player player = new Player();
player.HealthChanged += Player_HealthChanged;
player.Health = 100; // 이벤트가 발생하고, 핸들러가 호출됩니다.
// 이벤트 구독 취소
player.HealthChanged -= Player_HealthChanged;
// 시도: 이벤트 핸들러 리스트를 직접 수정하려 함 - 이것은 불가능하며 컴파일 오류 발생
player.HealthChanged = new EventHandler(Player_HealthChanged); // 컴파일 오류 발생
}
private static void Player_HealthChanged(int newHealth)
{
Console.WriteLine("Player's health changed to: " + newHealth);
}
C#
복사
실질적으로 이벤트는 코드 컨벤션, 즉 코딩 규칙을 강제하는 것과 같습니다. 일반적으로 delegate와 같은 이벤트는 private로 선언하여 외부에서 접근할 수 없도록 만들고, 함수로만 추가 삭제를 할 수 있습니다. 이것을 간편하게 만든 것이 바로 이벤트입니다.
Action
Action은 델리게이트의 한 형태로, 특별히 반환 값이 없는 메서드(즉, void 반환 타입)를 참조하는 데 사용됩니다.
Action 델리게이트는 0개에서 16개의 매개 변수를 가질 수 있으며, 사용하는 매개 변수의 타입에 따라 Action<T>, Action<T1, T2>, ... Action<T1, T2, ..., T16>과 같이 선언할 수 있습니다.
Action 사용
Action printMessage = () => Console.WriteLine("Hello, Action!");
printMessage(); // 출력: Hello, Action!
Action<int, int> printSum = (a, b) => Console.WriteLine($"The sum is: {a + b}");
printSum(5, 3); // 출력: The sum is: 8
public class EventPublisher
{
public event Action OnCustomEvent;
public void TriggerEvent()
{
OnCustomEvent?.Invoke();
}
}
public static void Main()
{
var publisher = new EventPublisher();
publisher.OnCustomEvent += () => Console.WriteLine("Custom event triggered!");
publisher.TriggerEvent(); // 출력: Custom event triggered!
}
public static void ExecuteAction(Action action)
{
Console.WriteLine("Before action");
action();
Console.WriteLine("After action");
}
public static void Main()
{
Action myAction = () => Console.WriteLine("Action executed");
ExecuteAction(myAction); // 출력: Before action, Action executed, After action
}
C#
복사
Func
Func 델리게이트는 반환 값을 포함하는 메서드를 참조하는 데 사용되는 델리게이트 유형입니다.
Func는 0개에서 16개의 매개 변수를 가질 수 있으며, 마지막 제네릭 타입은 델리게이트가 반환하는 값의 타입을 나타냅니다.
Func의 사용
Func<string> greet = () => "Hello, World!";
Console.WriteLine(greet()); // 출력: Hello, World!
Func<int, int, int> add = (x, y) => x + y; // 마지막 int가 반환값
Console.WriteLine(add(5, 3)); // 출력: 8
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(x => x % 2 == 0).ToList();
// Where문 자체가 Func<T,bool> 이랑 같음. 즉, numbers의 각 요소마다 bool값을 반환하는 함수.
evenNumbers.ForEach(x => Console.WriteLine(x)); // 출력: 2, 4
public static void PrintResult(Func<int> operation)
{
Console.WriteLine($"Result: {operation()}");
}
PrintResult(() => 42); // 출력: Result: 42
Func<Task<string>> fetchData = async () => {
await Task.Delay(1000); // 1초 대기를 시뮬레이션
return "Data fetched";
};
var data = fetchData();
Console.WriteLine(data.Result); // 출력: Data fetched
C#
복사