본문 바로가기

C#

C# 이벤트(Events)

1. Delegate(대리자) 코드의 특징: 방송자(BroadCaster)구독자(Subscriber)의 역할로 나뉨.

  • 방송자(BroadCaster): delegate 필드*가 있는 곳. delegate를 언제 호출할지 결정함.
  • 구독자(Subscriber): 방송자의 delegate를 +=, -= 연산자로 메서드를 등록하는 형식.
                             구독자끼리 독립이며 서로 알지 못함.

*구조체나 클래스의 멤버 변수


C# 이벤트*(Events)의 목적
대리자(Delegate)의 방송 및 구독 형식만 노출. 즉 "=" 연산 등을 무효화해서 구독자끼리 간섭하지 못하게 함.

*용어가 상당히 헷갈리게 지어졌는데 엄밀히는 이벤트 형식은 이벤트 핸들러라고 부르는 것이 맞다고 본다.
(그래서 뒤에 표준 이벤트 형식을 이벤트 핸들러라고 명명한 것으로 보인다.)
그래서 event의 객체명에 항상 핸들러가 붙는 것이다.
이벤트는 말그대로 프로그램 내에서 일어나는 변화나 신호(마우스 클릭 등) 그 자체일 뿐이고
C#의 이벤트는 그 변화를 관찰하기 위해서 대리자(함수의 꾸러미)를 특수한 형태로 제한한 것이기 때문이다.
그래서 이벤트가 일어날 때 함께 일어나도록 이벤트가 발생되는 코드 내에 대리자를 실행시키도록 끼워 넣는다.
이벤트 핸들러라는 이름의 뜻은 말 그대로 이벤트잘 예의주시하고 있다가 다루는 객체라는 뜻이다.
C# 이벤트(대리자)는 사건이 일어나는 현장에 있으면서 이를 구독한 이벤트 핸들러가 작동하도록 중계한다.
즉 C#의 이벤트는 직접적인 사건이 아니지만 현장에 있으므로 이벤트라고 하면서도 동시에 이벤트 핸들러인 것이다.

2. 이벤트 선언 방법: delegate 정의 → 접근자 뒤에 event 키워드를 넣어 delegate 선언.

public delegate void CustomEventHandler (int oldNum, int newNum); //delegate

public class Broadcaster
{
	int num;
	public event CustomEventHandler CustomEvent; //event delegate
 	public int Num 
	{
 		get => state;
		set
		{
			if(num == value) return; 
			//변화된 값이 없으면 빠져나감.
			int oldNum = num;
			num = value;
			if(CustomEvent != Null)
			//구독자가 있는지 체크
				CustomEvent(oldNum, num);
				//변화된 값이 있으면 방송(이벤트 발생)
		}
	}
}
  • Broadcaster 클래스 안에서는 CustomEvent에 전부 접근 가능하고, CustomEvent를 delegate처럼 사용 가능.
  • Broadcaster 클래스 밖에서는 "+=, -=" 연산만 수행 가능. (구독하기)
  • CustomEvent를 작동하면 구독했던 모든 함수가 작동된다. (구독자에게 방송됨)

 

event를 사용하지 않아도 똑같이 작동하지만 다음과 같은 것이 가능해진다.

  • CustomEvent를 클래스 바깥에서 완전히 바꿀 수 있다. (구독자 갈아치우기, 구독자 해제 등)
  • 구독자가 방송을 할 수 있다. (클래스 바깥에서 CustomEvent를 맘대로 작동함.)

즉, 구독자끼리 독립되지 않고 간섭할 수 있다는 뜻이다.

참고문헌: C# 8.0 in a Nutshell, Joseph Albahari. Eric Johannsen. pp158-160.