C#

이벤트(Event)

코다람쥐 2022. 1. 26. 14:12

1. delegate의 문제점

delegate는 사용하기 편하지만 main함수에서도 델리게이트 객체에 직접 접근이 가능하다는 문제점이 있다.

        public delegate void OnInputKey();
        static void Test()
        {
            Console.WriteLine("Test 호출");
        }
        static void Test2()
        {
            Console.WriteLine("Test2 호출");
        }
        static void UseOnInputKey(OnInputKey inputKey)
        {
            inputKey();
        }
        static void Main(string[] args)
        {
            OnInputKey inputKey = new OnInputKey(Test);
            inputKey += Test2;

            UseOnInputKey(inputKey); // 간접사용
            inputKey(); // 직접사용
        }

 

위의 코드를 분석해보면 delegate에 Test함수와 Test2 함수를 델리게이트 inputKey에 추가하고 정보은닉을 위해서 UseOnInputKey()함수를 통해서만 간접적으로 inputKey를 호출하는 클래스이다.

그런데 inputKey()를 main함수에서도 직접접근 할 수도 있다. 만약 inputKey에 중요한 정보가 담겨져 있다고 가정을 했을 때 이런식으로 직접 사용하는 것은 매우 위험할뿐더러 객체지향 관점에서도 좋지 못하다.

이러한 문제를 해결하기 위해 나온것이 event이다.

 

2. event

event는 유튜브의 구독의 개념과 비슷하다

유튜버를 구독하면 유튜버가 새 영상을 올리는 순간 우리에게 영상이 업로드 되었다고 메시지가 전달된다.

이처럼 event도 함수를 구독하면 특정한 기능이 실행되는 순간 구독한 함수에게 메시지를 전달하는 역할을 한다.

 

그리고 이벤트를 사용하면 외부에서 직접 호출하는 것을 막아주고 클래스 내부에서만 호출이 가능해진다.

 

event설명을 위한 InputManager클래스

    class InputManager
    {
        public delegate void AddOne(ref int n);
        public static event AddOne addOne;

        int n = 1;
        public void UseAddOne()
        {
            if (Console.KeyAvailable == false) // 입력이 없으면 함수종료
                return;

            ConsoleKeyInfo info = Console.ReadKey();

            if(info.Key == ConsoleKey.B) // 키보드에서 B가 입력이 되면
            {
                //addOne실행하고 값을 출력;
                addOne(ref n); 
            }   
        }
    }

위 클래스는 복잡해보이지만 간단하게 설명하면 B키가 입력되는 순간 n의 값을 1증가시키는 클래스이다.

 

        public delegate void AddOne(ref int n);
        public static AddOne addOne;

여기를 살펴보면 Addone addone은 (void형 - ref int형)의 함수를 인자로 받는 델리게이트이다.

public으로 선언되었기 때문에 외부에서도 마음대로 호출이 가능하다.

event선언방법

        public delegate void AddOne(ref int n);
        public static event AddOne addOne;

AddOne 앞에 델리게이트 객체 AddOne 앞에 event키워드를 붙여주었다. 

일단 이렇게 event를 선언하면 더 이상 외부에서 직접 호출이 불가능해진다.

 

event사용방법

        static void addOneTest(ref int n)
        {
            n++;
            Console.WriteLine(n);
        }
        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();
            InputManager.addOne += addOneTest;

            while (true)
            {
                inputManager.UseAddOne(); // 키보드에서 b를 누르면 실행이됨
            }
        }

addOneTest함수는 인자로 들어온 값을 1증가시키고 출력하는 함수이다.

여기에서 addOne함수를 구독할 수 있는데 구독하는 방법은 +=연산자를 사용하면된다.(반대로 구독을 취소하는 방법은 -=이다.)

addOne함수를 구독하였기 때문에 UseAddOne()함수를 통해 addOne이 간접적으로 실행이되고 콘솔창에서 b를 누르면 addOneTest함수가 호출되어 n의 값이 1씩 증가하는 걸 볼 수 있다.