Delegate +@

Clean·2025년 3월 27일

델리게이트 (Delegate)

  • 델리게이트(delegate)는 함수를 가리키는 참조타입이다.

  • delegate 변수에는 함수를 저장하고, 원하는 타이밍에 실행시킬 수 있다.

  • 이벤트(Event)콜백(Callback) 에서 자주 사용된다.


문법

// 덧셈 함수
public static float Plus(float left, float right) { return left + right; }

// delegate 선언 (반환형과 매개변수를 지정)
public delegate int IntDel(int left, int right);

// delegate 변수에 덧셈 함수 할당
IntDel intDel = Plus;

// delegate 실행
int result = intDel(5, 3);  // 8

특징

  • 함수를 저장하는 참조 타입이다.

  • 함수의 매개변수와 반환 타입이 동일해야 할당할 수 있다.

  • +=-= 연산자를 사용하여 여러개의 함수를 저장할 수 있으며,
    Invoke() 를 사용하여 할당된 함수들을 실행할 수 있다.

  • delegate는 불변 객체(Immutable Object)이므로,
    할당 연산을 수행할 때마다 새로운 인스턴스가 생성된다.


예시

public delegate float Delegate1(float left, float right); // delegate 선언

public class Program
{
    public static float Plus(float left, float right) { return left + right; }  // 덧셈 함수 
    public static float Minus(float left, float right) { return left - right; } // 뺄셈 함수

    static void Main()
    {
        Delegate1 del = Plus;    // delegate에 덧셈 함수 할당
        Console.WriteLine(del(10, 5)); // 15 출력

        del = Minus;    // 뺄셈 함수로 변경 가능
        Console.WriteLine(del(10, 5)); // 5 출력

        del += Plus;    // delegate 체인 (여러 개 추가 가능)
        Console.WriteLine(del.Invoke(10, 5));
    }
}

델리게이트 체인 (Delegate Chain)

Action<string> action;

// 함수 할당
action = Message;
action("안녕하세요?");

// 여러 개의 함수 추가
action += Message;
action("반갑습니다."); // Message가 두 번 실행됨

// 특정 함수 제거
action -= Message;
  • 앞서 말한 +=, -= 연산자로 여러 함수를 실행할 수 있다.

  • += 연산자로 등록된 순서대로 실행된다.

  • -= 연산자로 동일한 함수를 제거할 때는 제일 마지막에 등록된 함수가 제거된다.


일반화 델리게이트 (Generic Delegate)

  • 같은 반환타입과 같은 매개변수를 가진 델리게이트끼리는 덮어씌우기가 안되는데,
    이 때 내장되어있는 Action<>, Func<> 델리게이트를 사용한다.

문법

Func<T, T, 반환형> // 매개변수는 더 추가할 수 있지만 반환형은 항상 마지막

Action<T>

특징

  • 반환 타입이 voidAction<T>, 그 외에는 Func<T> 를 사용한다.

Callback

  • 콜백(callback)은 특정 이벤트(event)가 발생했을 때 실행되는 함수이다.

  • 델리게이트를 사용하여 콜백을 구현할 수 있다.

  • 보통 함수를 매개변수로 전달하여 실행하는 방식으로 동작한다.

  • 이벤트(event)와 달리, 특정 객체의 상태와 무관하게 실행할 수도 있다.


예시

public class Callback
{
    public class File
    {
        public void Save()
        {
            Console.WriteLine("저장합니다");
        }

        public void Load()
        {
            Console.WriteLine("불러옵니다");
        }
    }
    public class Button
    {
        public delegate void ClickListener();
        public ClickListener? clickEvent; 		// ?로 null일 수도 있음을 명시

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

사용 예시

Callback.File file = new Callback.File();
Callback.Button button = new Callback.Button();

// 버튼 클릭 이벤트에 Save 함수 할당
button.clickEvent = file.Save;
button.clickEvent(); // 저장합니다 출력

// 버튼 클릭 이벤트에 Load 함수 할당
button.clickEvent = file.Load;
button.clickEvent(); // 불러옵니다 출력

이벤트 (Event)

  • 이벤트(event)는 특정 사건이 발생했을 때 실행되는 delegate이다.

  • event 키워드를 사용하여 선언하면, +=-= 연산자만 사용 가능하다.
    즉, =로 외부에서 직접 호출할 수 없어 안전하게 사용할 수 있다.


예시

class Player
{
    public event Action OnAction; // event 키워드

    public void Attack()
    {
        Console.WriteLine("플레이어가 공격");
        OnAction?.Invoke();
    }
}

class Monster
{
    public void Hit()
    {
        Console.WriteLine("공격받음");
    }
}

static void Main()
{
    Player player = new Player();
    Monster monster = new Monster();

    player.OnAction += monster.Hit;
    player.Attack();
    // 플레이어가 공격
    // 공격받음
}

익명 함수 & 람다식

익명 함수 (Anonymous Function)

IntDel intDel1 = delegate (int[] values)
{
    int result = 0;
    foreach (var i in values)
        result += i;
    return result;
};
Console.WriteLine($"익명 함수 결과 : {intDel1?.Invoke(1, 3, 5, 7)}");
  • 함수명 없이 즉석에서 선언하는 함수이다.

  • 주로 재사용 여지가 없거나, 일회성으로 사용할 경우에 사용한다.


람다식 (Lambda expression)

IntDel intDel2 = (values) =>   // 매개변수가 하나면 괄호 생략가능 values
{
    int result = 0;
    foreach (var i in values)
        result += i;
    return result;
};
Console.WriteLine($"람다식 함수 결과 : {intDel2?.Invoke(1, 3, 5, 7)}");
Func<int, int, bool>   // <입력값, 입력값, 출력값>
    result 	 		   // 반환값
    = (x, y)           // (매개변수)
    => x == y;         // 조건문
    // 즉 result에 bool값이 들어간다.
  • 익명 함수를 더 간결하게 표현한 문법이다.

  • (매개변수) => { 실행 코드 } 형태를 사용한다.


MSW에서 사용하던 이벤트 시스템과는 차이가 있어 적응이 필요하지만,

델리게이트와 이벤트를 잘 활용하면 코드의 확장성이 좋아질 것 같다.

열심히 해보자

0개의 댓글