본문 바로가기
C#/[루키스] 실전 문법

[C# 섹션 8] Event

by 묻공러 2025. 6. 25.

# delegate 문제점

delegate는 치명적인 단점이 있다

외부에서 언제든지 누구나 호출이 가능하다는 것이다

 

아래의 예시를 보면,

InputManager의 delegate 객체인 InputKey를

외부에서 아무나 호출이 가능하다는 것이다

// InputManager

namespace CSharp
{
    class InputManager
    {
        public delegate void OnInputKey();
        public OnInputKey InputKey;

        public void Update()
        {
            if (Console.KeyAvailable == false)
                return;

            ConsoleKeyInfo info = Console.ReadKey();
            if(info.Key == ConsoleKey.A)
            {
                InputKey();
            }

        }

    }
}
namespace CSharp
{
    internal class Program
    {
        static void OnInputTest()
        {
            Console.WriteLine("Input Received");
        }

        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();
            inputManager.InputKey += OnInputTest;

            inputManager.InputKey(); // 외부에서 호출 가능
        }
    }
}

 

# private?

위의 문제를 해결하기 위해서

델리게이트 객체를 private으로 작성을 하는 방안은 불가능하다

그 이유는 private을 했기에 외부에서 바인드와 호출 모두 막히기 때문이다

// InputManager

public delegate void OnInputKey();
public OnInputKey InputKey;

 

// Main

namespace CSharp
{
    internal class Program
    {
        static void OnInputTest()
        {
            Console.WriteLine("Input Received");
        }

        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();
            inputManager.InputKey += OnInputTest; // 바인드 불가 (오류 발생)

            inputManager.InputKey(); // 호출 불가 (오류 발생)
        }
    }
}

 

# event

이러한 기존 delegate의 문제점을 보완한 것이 event 키워드이다

외부에서 호출이 불가능하도록 하기 위해서는

delegate의 객체를 event 키워드를 통해 만들면 된다

참고로, 둘 다 접근지정자는 동일해야 한다

// InputManager

namespace CSharp
{
    class InputManager
    {
        public delegate void OnInputKey();
        public event OnInputKey InputKey; // event 키워드 활용

        public void Update()
        {
            if (Console.KeyAvailable == false)
                return;

            ConsoleKeyInfo info = Console.ReadKey();
            if(info.Key == ConsoleKey.A)
            {
                InputKey();
            }

        }

    }
}
// Main

namespace CSharp
{
    internal class Program
    {
        static void OnInputTest()
        {
            Console.WriteLine("Input Received");
        }

        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();
            inputManager.InputKey += OnInputTest;

            while (true)
            {
                inputManager.Update();
            }
        }
    }
}

 

 

이처럼

event를 통해 구독 신청/취소는 가능하지만

event를 외부에서 호출이 불가능하기에

delegate는 event 키워드를 이용해 객체를 생성하는 것이 권장된다

 

# ObserverPattern

옵저버 패턴은 디자인 패턴 중 하나로

객체들 간의 일대다(one-to-many) 의존성을 정의하는 방식이다

한 객체의 상태가 변경되면,

그 객체를 주시하고 있는 모든 다른 객체들(관찰자)에게

자동으로 변경 사실을 알리고 업데이트하는 방식이다

C#에서는 이러한 패턴을 delegate와 event를 통해 쉽게 만들 수 있다

'C# > [루키스] 실전 문법' 카테고리의 다른 글

[C# 섹션 8] Exception  (2) 2025.06.26
[C# 섹션 8] Lambda  (0) 2025.06.25
[C# 섹션 8] Delegate  (0) 2025.06.25
[C# 섹션 8] Property  (0) 2025.06.24
[C# 섹션 8] Interface  (0) 2025.06.24