Delegate(대리자) 와 Event

이승한·2023년 7월 9일
0

CSharp

목록 보기
11/25

Delegate(대리자)

코드를 작성할때 순차적으로 만들어 왔는데 상대에게 거꾸로 요청할 수 있는 상황이 빈번하게 일어나는데 이러한 일을 대리자로 처리할 수 있다.

한줄로 설명하자면, 함수 자체를 인자로 넘겨주는 방법 (callback방식)이라고 생각하면 된다.

class Program
{
	
    //대리자
    delegate int OnClicked(void);
    //OnClicked는 대리자니까 int와string과같은 형식으로 함수자체를 인자로 넘겨주는 형식이라고 생각한다.
    //반환 :int 입력 :void
    //OnClicked는 delegate 형식의 이름이다.
    
	//UI
    static void ButtonPressed(OnClicked clickedFunction  //버튼이 눌렸을때 함수를 호출할 인자를 넘겨주고 싶다.)
    {
    	//함수를 호출
        clickedFunction();
    }
    
    static int TestDelegate() //실제 대리자에서 구현해야하는 부분 (로직)
    {
    	Console.WriteLine("Hello Delegate");
        return 0;
    }
    static int TestDelegate2()
    {
    	Console.WriteLine("Hello Delegate 2");
        return 0;
    }
    
	static void Main(string[] args)
    {
    	//delegate ( 대리자 )
        //ButtonPressed(TestDelegate); 간단히 호출하는방법도 있다.
        
        OnClicked clicked = new OnClicked(TestDelegate);
        clicked();
        
        //대리자는 체인이 가능하다. 여러개의 함수를 동시에 넘겨줄 수 있다.
        clicked += TestDelegate2;
        
        
        ButtonPressed(clicked);
        
    }
}

Event

대리자의 치명적인 단점이 하나 존재하는데
설계적으로 볼때 위에 코드에서 Delegate로 구현한 함수를 누구나 호출 할 수 있다는게 문제이다.
위에 코드를 부분만 가져와서 설명

delegate int OnClicked(void);

//UI
static void ButtonPressed(OnClicked clickedFunction)
{
    //함수를 호출
    clickedFunction();
}

static void Main(string[] args)
{
	OnClicked clicked = new OnClicked(TestDelegate);
    clicked();  // 누구나 호출할 수 있다는 문제부분
}

위의 코드에서 만약 clickedFunction()이 굉장이 중요한 부분이고 함부로 호출되면 안되는 부분이라 할 때 메인 함수의 clicked()는 누구나 호출할 수 있기에 설계적인 문제가 생긴다고 볼 수 있다.

근데 이러한 대리자를 랩핑해줄 수 있는 Event라는 문법이 있다.

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();
        }     
    }
  }
  
  class Program
  {
      static void OnInputTest()
      {
          Console.WriteLine("Input Reveived!");
      }
      static void Main(string[] args)
      {

          InputManager inputManager = new InputManager();
          inputManager.InputKey += OnInputTest; //구독신청
          while (true)
          {
              inputManager.Update();
          }
          
          //inputManager.InputKey; 더이상 그냥 호출할 수 없다.
            
       }
   }

InputManager라는 키 입력을 받는 클래스를 만들고
A라는 키가 입력되었을 때 모두에게 알려주는 코드를 만든다고 했을 때 키를 받아 알려줘야하니
대리자로 OnInputKey를 선언하고 한번더 Event로 랩핑해준다고 생각하면 된다.
그러면 메인함수에서 호출 하려하면 호출할 수 없다.
대신 +=나 -=로 구독,구독취소를 할 수 있다.

그리고 추가로 구독자를 모집한 다음에 특정 이벤트가 발생했을 때 구독자들한테 메시지를 뿌리는 방식을 ObSERVER Pattern이라 한다.

0개의 댓글