1 분 소요

먼저, 이런 상황을 가정해본다.

순차적으로 진행되는 일이 아니라, 일을 해달라고 요청이 들어오는 경우

예) UI 작업을 할 때.

버튼을 누르면 작동하는 경우, 아래와 같은 코드를 만들었다고 하자.

static void ButtonPressed()
{
    // codes
}
  • 이렇게 하면…
    • UI에 관련된 코드와 게임로직이 섞여있게 된다.
    • 현실적인 문제 : 나중에 수정하기가 어렵다.
    • 그래서 함수를 인자로 넘겨주는 방식을 생각하게 된다. (필요할 때 역으로 호출하는 방식)
      static void ButtonPressed( /* 함수를 인자로 넘김 */)
      {
        // 함수 호출()
      }
      

Delegate 활용

delegate int OnClicked();
        /*
         delegate형식이며, 함수 자체를 인자로 넘겨주는 형식. 
        반환은 int, 입력은 없음
        이름은 OnClicked
   */
static void ButtonPressed(OnClicked clickedFunction)
{
    clickedFunction();
}

static int DelegateTest()
{
    Console.WriteLine("delegate on!");
    return 0;
}

static void Main(string[] args)
{
    ButtonPressed(DelegateTest);
}
  • 함수자체를 인자로 넘겨주게 된다.
  • 다양한 규칙으로 동작하는 하나의 함수를 만들 때 delegate 형식이 유용할 수 있다.
  • main 함수 작동부분은 내부적으로는 아래와 같이 동작한다.
    // OnClicked 형식으로 새로운 객체 생성(DelegateTest함수를 들고있음)
    OnClicked smth = new OnClicked(DelegateTest);
    // ButtonPressed의 매개변수로 전달
    ButtonPressed(smth);
    

Delegate는 Chaining이 가능하다 : 호출되는 함수를 추가할 수 있음.

static int DelegateTest2()
{
    Console.WriteLine("plus : delegate on!");
    return 0;
}

static void Main(string[] args)
{
    OnClicked smth = new OnClicked(DelegateTest);

    smth += DelegateTest2;

    ButtonPressed(smth);

                //ButtonPressed에서만 이용하려고 했는데, 이런 식으로 마음대로 호출이 가능함. 
                smth();
}
  • 아무나 호출할 수 있기 때문에, 설계적인 부분에서는 문제가 있을 수 있다.
  • 보완을 위해서 delegate를 wrapping하는 문법이 있다. : event

Event 이벤트

// InputManager.cs 참고
class InputManager
{
// Observer Pattern
    public delegate void OnInputKey();
    public event OnInputKey InputKey;
    // 이 InputKey를 구독해놓으면, call 시 다같이 실행되는것.

    public void Update()
    {
        if (Console.KeyAvailable == false)
            return;
        ConsoleKeyInfo info = Console.ReadKey();
        if (info.Key == ConsoleKey.A)
        {
            // 모두에게 알려준다! : call back 방식으로 구현해야 함. 
            InputKey();
        }
    }
}
  • delegate형식을 event 형식으로 한 번 더 싸놓는 것.
  • InputKey에 마우스 올려보면 그냥 OnInputKey 타입으로 나옴.
  • Observer Pattern : event를 통해서 구독자를 모집한 다음, 특정 이벤트가 발생했을 때 구독자들을 실행하는 방식 ```c# // Main static void OnInputTest() { Console.WriteLine(“Input received!”); }

static void Main(string[] args) { InputManager input = new InputManager(); // 구독신청 input.InputKey += OnInputTest;

while(true)
{
    input.Update();
} } ``` - InputKey에도 static 함수 더해놓고 call되도록 설정할 수 있다. - **다만, delegate와는 다르게 아래의 경우처럼 마음대로 호출할 수 없다.** - 구독 신청이나 구독 취소만 가능하다. ```c# //input.InputKey(); ```

댓글남기기