C# delegate, event

장현태입니다·2025년 3월 27일

Delegate(대리자)

특정 매개변수 목록 및 반환 형식이 있는 함수에 대한 참조를한다
대리자 인스턴스를 통해 함수를 호출 할 수 있다
쉽게 말해 변수는 int number = 10;와 같이 함수도 이런 형식으로 Function1 func = Function2;와 같은 형식으로 함수의 주소를 가리키는 참조를 담을 수 있는 형식이다


delegate의 구성:
delegate 반환형 델리게이트이름(매개변수);
delegate float DelegateMethod1(float a, float b);
이때 delegate의 핵심은 반환형, 매개변수에 집중해줘야한다.



이때 반환형과, 매개변수를 집중해서 작성해야하는 이유가 Plus함수의 반환형 float 매개변수 float가 일치해야 delegate에 할당 가능하다.

delegate를 사용하는 이유중 하나인 callback에 대해 알아보겠다

Callback

델리게이트를 이용하여 특정조건에서 반응하는 함수를 구현한다
우리가 평소에 사용하던 함수의 호출(call)이 아닌 역으로 호출 받을 때 반응을 참조하여 역호출하는(call back) 시스템이다.

이미 우리가 알던 함수를 사용하면 되지 왜 callback을 사용하는가?
이유는 플레이어나 게임에서 함수를 실행할때 언제 일어날지 모르는 미래의 상황에 계속 신경쓰면서 호출할 수는 없기 때문이다
이를 해결하는 방법으로 상황이 발생한다면 그때 일어난 일에 대한 함수를 호출하면 되기때문에 callback을 사용한다.

택배로 예를 들어보자면 손님이 택배가 왔는지 call 3번 그이상을 호출 하는거보다 택배가 도착하고 callback한번 호출하는것이 더 효율적이다 라고 생각하면 된다.

그래서 콜백은 어떻게 사용하는데???
아래의 코드를 분석해보자

File, Player 클래스는 평소와 다를바 없이 작성해주고, 인스턴스화 해준다. 그리고 Button 클래스에서 delegate를 작성해주면서 delegate의 변수도 지정해주고 ButtonClick함수가 실행 됐을 때 delegate 함수를 실행 해주는것으로 Main함수에서 Button클래스 인스턴스화 한후에 delegate 변수를 지정해주면서 각 클래스의 함수를 대입시키고 인스턴스화했던 변수에 ButtonClick()을 실행하므로 callback을 실행한다.

하나 더 예를 들어보자



게스트가 전화를 기다리는데 계속 물어볼 수 없는 상황이라 그쪽에서 전화주시길 기다릴게요~ 하는 상황이다. 이렇게 코드를 작성하면 다음과 같이 출력된다.

delegate chain

델리게이트 체인이란 하나의 델리게이트를 사용해 여러개를 호출하는 방법이다. 왜 이런방법을 사용하냐?? 만약 이전에 게스트 한명만 있었다면 문제가 없는데 여러명이 연락을 기다린다 한다면 모두를 다 호출시킬 필요가 있다 그럴때 연락 왔습니다~ 라는 같은 메세지를 하나하나 다 만들어서 호출하면 의미가 없어지기 때문에 delegate chain이 필요하다.

먼저 delegate에서 C#에서 편하게 제공하는 방법이 있는데 이는
반환형과 매개변수에 집중하면 된다는 방법으로 Func, Action으로 사용되며 delegate generic으로 분류된다.

1) Func delegate
public static 반환형 Test(매개변수1,매개변수2,...){return 0;}
Func<매개변수1,매개변수2,...,반환형>func = Test;

public static float Test (float a, float b){return 0;}
Func<float,float,float>func = Test;

형식으로 작성하며, Action은 반환형이 void 일경우 사용가능하다

2) Action delegate
public static void Test(float x, int y, string z){}
Action<float,int,string> ac = Test;

처럼 만들 수 있다

delegate Chain


이처럼 Action을 사용햐여 += 을 통해 함수들을 3개 동시에 출력할 수 있다. 그와 동시에 -=를 통해 함수를 줄일수도 있다.

하지만 문제가 하나 있는데 마지막에 대입을 진행할 경우 앞에 있던 모든 것이 사라지고 대입했던 함수만 호출된다.

이러한 방법을 해결하기 위해 event 키워드를 사용한다

Event

일련의 사건이 발생했다는 사실을 다른 객체에게 전달
델리게이트의 일부 기능을 제한하여 이벤트의 용도로 사용


이벤트 키워드를 사용하는 이유는 두가지 있다.

첫번째:
위에서 말했듯이 대입을 통해 이전에 함수실행을 원했던방향이 아니라 사라지는것을 방지하기 위해서 사용한다

두번째:



이렇게 ainmal을 혼자 호출할경우 다른 상황이 발생하지 않고 혼자 함수를 실행하고 마치기 때문에 event키워드가 필요하다



코드와같이 animal.AnimalCry()하나만 호출했을 뿐인데 다른 이벤트가 발생 하는것을 볼 수 있다.

++추가(Event예시)
Event를 이용해 Player의 갑옷기능과 갑옷의 내구도가 떨어졌을경우 해제하는 이벤트, player가 공격했을때 액세서리가 공격하는 event를 적용시켰다.

갑옷이 부셔졌을경우 자동으로 이벤트 적용을 해줬고, AttackAccessories 클래스를 상속을 통해 각 액세서리 클래스에 생성자를 만들어주고 player.AccessoriesAttack 이벤트를 적용해서 각 액세서리의 함수를 자동 실행시켜주었다.

0개의 댓글