#델리게이트 (Delegate) #콜백함수 #체인 #일반화

sejun-Lee·2025년 3월 27일

대리자 (Delegate)


특정 매개 변수 목록 및 반환 형식이 있는 함수에 대한 참조
대리자 인스턴스를 통해 함수를 호출 할 수 있음

      <델리게이트 정의>
       delegate 반환형(void,float) 델리게이트이름(매개변수들);
public delegate float DelegateMethod1(float left, float right);     // 함수를 대신 실행시킬 뿐이라서 { } 내용은 필요 없음
public delegate void DelegateMethod2(string str); 


internal class Program
{
    public static float Plus(float left, float right) { return left + right; }
    public static float Minus(float left, float right) { return left - right; }
    public static float Multi(float left, float right) { return left * right; }
    public static float Divide(float left, float right) { return left / right; }
    public static void Message(string message) { Console.WriteLine("메세지로 {0}을 전송합니다.", message); }


    static void Main(string[] args)
    {
        DelegateMethod1 delegate1 = Plus;
        //DelegateMethod1 delegate1 = Message;  // 불가능 delegate의 반환형이 float라서 string은 저장 불가능!!
        DelegateMethod2 delegate2 = Message;    // DelegateMethod2 는 void와 매개변수가 string을 받는거라서 가능.
        
        // 원래는 이렇게 사용. Invoke 부르다
        delegate1.Invoke(20f, 10f);         // 보관한 함수를 부르는 기능 -> 30
        delegate1(20f, 10f);                // Invoke를 간략하고 직관적으로 사용하기 위한 문법 허용 -> 30

        float result;
        result = delegate1(20f,10f);
        Console.WriteLine(result);      // 30

        // <델리게이트 사용>
        // 반환형과 매개변수가 일치하는 함수를 델리게이트 변수에 할당
        // 델리게이트 변수에 참조한 함수를 대리자를 통해 호출 가능

        delegate1 = Plus;
        Console.WriteLine(delegate1(20f, 10f));     // Plus(20f, 10f) = 30
        delegate1 = Minus;
        Console.WriteLine(delegate1(20f, 10f));     // Minus(20f, 10f) = 10
        delegate1 = Multi;
        Console.WriteLine(delegate1(20f, 10f));     // Multi(20f, 10f) = 200
        delegate1 = Divide;
        Console.WriteLine(delegate1(20f, 10f));     // Divide(20f, 10f) = 2

    }
}

콜백함수(Callback)


  • 델리게이트를 이용하여 특정 조건에서 반응하는 함수를 구현
  • 함수의 호출(Call)이 아닌 역으로 호출받을 때 반응을 참조하여 역호출(Callback)
public class File
{
    public void Save()
    {
        Console.WriteLine("저장하기 합니다.");
    }

    public void Load()
    {
        Console.WriteLine("불러오기 합니다.");
    }
}

public class Button
{
    public delegate void ClickListener();
    public ClickListener clickListener;

    public void Click()
    {
        if (clickListener != null)
        {
            clickListener();
        }
    }
}

public class Player
{
    public void Jump()
    {
        Console.WriteLine("플레이어가 점프합니다");
    }
}

static void Main(string[] args)
{
    File file = new File();
    
	// 하나의 콜백함수로 여러 기능을 담아 특정 조건에 맞게 출력
    Button saveButton = new Button();
    saveButton.clickListener = file.Save;	//save 기능을 콜백함수에 담는다

    Button loadButton = new Button();
    loadButton.clickListener = file.Load;	//load 기능을 콜백함수에 담는다

    saveButton.Click();     // 저장하기
    loadButton.Click();     // 불러오기


    Player player = new Player();
    Button jumpbutton = new Button();
    jumpbutton.clickListener = player.Jump;
    jumpbutton.Click();     // 점프하기
}

델리게이트 체인(Chain)


델리게이트 변수에 여러게의 함수를 참조하는 방법

  • 하나의 델리게이트 변수에 여러 개의 함수를 할당하는 것이 가능
  • +=, -= 연산자를 통해 할당을 추가하고 제거할 수 있음
  • = 연산자를 통해 할당할 경우 이전의 다른 함수들을 할당한 상황이 사라짐
static void Main(string[] args)
{
    Action action;
    action = Func1;      // 델리게이트에 Func1 로 초기화
    action += Func2;     // 델리게이트에 Func2 추가 참조
    action += Func3;     // 델리게이트에 Func3 추가 참조
    action += Func2;     // 같은 Func 중복 참조도 가능
    action();           // Func1 - Func2 - Func3 -Func2
    Console.WriteLine();

    action -= Func2;    // 저장한 Func2 참조 제거도 가능
    action();           // Func1 - Func2 - Func3
    Console.WriteLine();

    action = Func3;     // 델리게이트에 = 을 통해서 대입하는 경우, 이전의 참조된 상황이 사라짐
    
    action -= Func1;    // 델리게이트에 참조되지 않은 함수를 제거하는 경우, 해당 작업이 무시됨
    action();           // Func3


    action = Func2;     // 델리게이트에 참조된 상황이 없을경우 터진다.
    action -= Func2;
    //action();            // 꼭 있을때만 호출!!

    if (action != null)     // 델리게이트에서 참조를 제거할 경우 참조하고 있는 함수가 없는 경우를 조심!!
    {
        action();
    }

}

public static void Func1() { Console.WriteLine("Func1"); }
public static void Func2() { Console.WriteLine("Func2"); }
public static void Func3() { Console.WriteLine("Func3"); }

일반화(Generic) 델리게이트


개발과정에서 많이 사용되는 델리게이트의 경우 일반화된 델리게이트를 사용

<Func 델리게이트>

  • 반환형 매개변수를 지정한 델리게이트
  • Func<매개변수1, 매개변수2, ..., 반환형>
int Plus(int left, int right) { return left + right; }
int Minus(int left, int right) { return left - right; }

        void Main1()
        {
            Func<int, int, int> func;
            func = Plus;
            func = Minus;
        }

<Action 델리게이트>

  • 반환형이 void 이며 매개변수를 지정한 델리게이트
  • Action<매개변수1, 매개변수2, ...>
   void Message(string message) { Console.WriteLine(message); }

        void Main2()
        {
            Action<string> action;
            action = Message;
        }

<Predicate 델리게이트>

  • 반환형이 bool, 매개변수가 하나인 델리게이트
bool IsSentence(string str) { return str.Contains(' '); }

        void Main3()
        {
            Predicate<string> predicate;
            predicate = IsSentence;
        }
profile
초보 개발자

0개의 댓글