전체 코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp
{
    // Observer Pattern
    internal class InputManager
    {
        
        public delegate void OnInputKey();    
        public event OnInputKey InputKey; // 구독 신청     

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

            ConsoleKeyInfo info = Console.ReadKey();
            if (info.Key == ConsoleKey.A)
            {
                InputKey?.Invoke();  
            }
        }
    }
}
using System.ComponentModel;
using System.Numerics;
using System.Threading;
using System.Collections.Generic;

namespace CSharp
{

    class Program
    {
        
        // delegate의 설계적 단점이 존재
        // 누구나 호출 가능
        // 따라서 설계가 깨질 가능성이 있음

        // 이를 방지하기 위해 event란 문법이 있다
        public static void OnInputTest()      
        {
            Console.WriteLine("Input Received");
        }

        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();

            inputManager.InputKey += OnInputTest; // 구독신청

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




    }
}

🔔 이벤트란?

Event는 특정 상황이 발생했을 때,
외부에서 미리 등록해 둔 메서드들을 자동 호출하는 기능이다.

  • 내부에서는 이벤트를 발생시키는 역할
  • 외부에서는 이벤트에 함수들을 구독(등록)하는 역할
  • 옵저버 패턴(Observer Pattern)의 전형적인 구현

💡 이벤트 구조란?

구성요소설명
Delegate등록 가능한 함수 시그니처 정의
EventDelegate 기반으로 이벤트 객체 생성
등록 (Subscription)외부에서 이벤트에 함수 등록
발생 (Trigger)내부에서 특정 조건 시 이벤트 실행 (등록된 함수 호출)
호출 제한이벤트는 클래스 내부에서만 실행 가능

📥 이벤트 정의

1️⃣ InputManager 클래스 (이벤트 정의)

namespace CSharp_ETC
{
    internal class InputManager
    {
        public delegate void OnInputKey();    // ① 대리자 정의
        public event OnInputKey InputKey;     // ② 대리자 기반 이벤트 정의

        public void Update()                   // ③ 이벤트 발생 조건 체크
        {
            if (Console.KeyAvailable == false)
                return;

            ConsoleKeyInfo info = Console.ReadKey();
            if (info.Key == ConsoleKey.A)
            {
                InputKey?.Invoke();  // ④ 이벤트 발생 (구독자들에게 신호 보냄)
            }
        }
    }
}

2️⃣ Program 클래스 (이벤트 구독 및 실행)

namespace CSharp_ETC
{
    internal class Program
    {
        public static void OnInputTest()       // ⑤ 이벤트 발생 시 실행할 함수 정의
        {
            Console.WriteLine("Input Received");
        }

        static void Main(string[] args)
        {
            InputManager inputManager = new InputManager();

            inputManager.InputKey += OnInputTest; // ⑥ 이벤트 구독 (함수 등록)

            while (true)                         // ⑦ 키 입력 계속 체크
            {
                inputManager.Update();          // ⑧ 입력 체크 및 이벤트 발생
            }
        }
    }
}

🛠️ 예제 흐름 분석

단계설명
OnInputKey 대리자 정의 (void 반환, 파라미터 없음)
InputKey 이벤트 정의 (OnInputKey 타입)
키 입력 감지 (Update)
A 키 눌리면 InputKey 이벤트 발생 (등록된 함수 모두 호출)
OnInputTest 함수 정의 (A 눌리면 실행할 함수)
이벤트에 OnInputTest 함수 등록
무한 루프에서 계속 입력 체크
A 키 누르면 이벤트 발생 → OnInputTest 실행

🔗 이벤트 vs 델리게이트 차이점 완벽 정리

비교 항목DelegateEvent
역할함수 포인터 저장 및 실행특정 상황 발생 시, 등록된 함수 호출
외부 호출가능불가능 (내부에서만 호출)
캡슐화약함강함 (은닉성 강화)
등록 방법+= / -=+= / -=
체이닝가능가능
옵저버 패턴직접 구현 필요기본 지원

⚠️ 이벤트가 필요한 이유

델리게이트의 치명적 문제점

OnClicked clicked = Test;
clicked();  // 외부에서 누구나 호출 가능 (통제 불능)
  • 외부에서 막 눌러버리면? 데이터 꼬일 위험
  • 이벤트는 이 문제 해결 → "호출은 내부만 가능"

이벤트 보호 예시

public event OnInputKey InputKey;
  • 외부에서 InputKey() 호출하면 컴파일 에러!
  • 오직 InputManager 내부에서만 호출 가능

✅ 이벤트 흐름

1️⃣ 이벤트 정의

public delegate void OnInputKey();
public event OnInputKey InputKey;

2️⃣ 이벤트 발생 (내부)

if (info.Key == ConsoleKey.A)
{
    InputKey?.Invoke();  // 구독자 전원 호출
}

3️⃣ 이벤트 구독 (외부)

inputManager.InputKey += OnInputTest;

📦 이벤트 vs 델리게이트 선택 기준

상황선택
외부에서 직접 호출 가능해야 함Delegate
내부에서만 호출하고 외부는 등록만Event
버튼 클릭 같은 GUI 이벤트 처리Event
콜백 구현Delegate/Event 모두 가능

📜 이벤트 정리

키워드설명
Delegate메서드 참조 포인터
Event내부 발생 + 외부 등록
+=이벤트 구독
-=구독 해제
Invoke()이벤트 발생 (내부에서만)
Observer 패턴이벤트의 핵심 디자인 패턴

C# 이벤트 관용 패턴

public event EventHandler<EventArgs> SomethingHappened;
  • EventHandler<T> 사용하는 방식 추천 (표준 패턴)
  • 이벤트 인자 전달 필요할 때 매우 유용

profile
李家네_공부방

0개의 댓글