본문 바로가기
- C#

[C#] delegate, Action / Func / Predicate

by david_동근 2025. 8. 26.

예전 포스트에서 콜백 개념과 함께 한번 다뤘었지만, 다시 한번 정리해봤습니다.

마이크로 소프트 공식 홈페이지에 C# 에 대한 더 많은 내용이 담겨있답니당


 

delegate

델리게이트, 우리말로 대리자. (야 대리불러~  )

메서드 시그니처 (매개변수나 반환형) 가 같은 메서드를 가리키면서,

나중에 다른 클래스에서 크 메서드를 대신 호출할 수 있게 해주는 타입입니다.

Callback 콜백 함수, 이벤트 처리 등에서 많이 사용합니다.

 

delegate 는 참조 타입 객체입니다. 그렇기에 생성 시 할당이 됩니다.

쉽게 생각해, 변수에다가 숫자나 문자열을 담듯이,

메서드를 담는 변수라고 생각해봅시다.

 

선언은 아래 처럼 할 수 있습니다.

public delegate void Notifier(string message);
// string 을 매개인자로, 리턴 없는 void 메서드를 담을 수 있는 타입을 만들었어용

 

등록해 호출하기 위해서는, 매개변수와 반환형이 같은지 늘 확인해야 합니다.

void ConsoleNotify(string msg) => Console.WriteLine(msg);
// 메서드를 Notifier 타입의 n 에 대입합니다요
Notifier n = ConsoleNotify;

 

아래와 같이 필요한 시점에서 (다른 클래스에서 대신 실행) 호출할 수 있습니다.

string str = "I luv U~";

n(str);
// 아래와 같은 행동입니당
ConsoleNotify(str);

 

 

delegate - null 확인

할당 된 콜백 메서드 (Subscriber 라고도 부르나 봐요) 가 없을 수도 있으니,

늘 null 을 호출하지는 않는지 체크해 안전하게 호출하도록 해야합니다.

Notifier n = null;

// 제일 간단하고 보기 좋지요
if (n != null)
	n("hi");

// 널라블 nullable 로 확인
n?.Invoke("hi");

// 이벤트 패턴, 스레드 안정성을 위해 로칼복사본으로 호출해용
var temp = n;
temp?.Invoke("hi");

 

 

Action / Func / Predicate

이 세개는 비슷비슷하기 때문에 한꺼번에 정리하도록 하겠습니다.

 

Action, void 라서 리턴값이 없는 콜백이기 때문에 그냥 실행만 하면 된다, 싶으면 사용합니다.

Action a0;                 // 매개변수 0개, void 반환형
Action<int> a1;           // int 1개, void
Action<int, string> a2;   // int, string 로 매개변수가 2개인 void 타입

사실 아래와 똑같습니다.

delegate void Action(); // 매개변수 없음
delegate void Action<T>(T n); // 매개변수 1개
delegate void Action<T1, T2>(T1 a, T2 b);  // 매개변수 2개

 

Func, 반환값이 있는 콜백으로 결과값을 돌려 받아야 한다면 사용합니다.

Func 는 <T1, T2, ... , Tn> 에서 마지막 인자가 반환형입니다.

Func<int> f0;                 // 매개변수 0개, 하지만 반환형은 int
Func<int, bool> f1;           // int 넣어서 -> bool 로 반환
Func<string, int, float> f2;  // 매개변수 2개 (string, int) -> float 반환

 

Predicate<T>, bool 리턴값으로 그냥 Func<T, bool> 과 다를 바가 없음

Predicate<int> p; // int -> bool, 그냥 Func<int, bool> 랑 똑같아용

 

List 정렬에 쓰이는 Comparison<T> 같은 경우는 Func<T, T, int> 와 똑같지만,

의도가 분명하니 사용되는 편입니다.

 

추가)

아래 몇가지 예재를 정리했습니다.

아래는 기본적인 콜백 사용 예시입니다.

public void OnClick(Action callback)
{
    // 어쩌구 저쩌구 코드들 수행 후
    callback?.Invoke(); // nullable 콜백
}

// 사용하고자 하는 곳에서 아래처럼
OnClick(() => Debug.Log("Clicked"));

 

아래처럼 생성 직후에 초기화하는 방법도 쓰입니다.

public T Create<T>(Action<T> init = null) where T : new()
{
    T obj = new T();
    init?.Invoke(obj); // 만든 직후, 넘겨준 초기화 로직 실행
    return obj;
}

// 아래처럼
Player player = Create<Player>(p => { p.Name = "pee"; p.Hp = 100; });

 

조건을 확인하는 용도로도 Predicate 를 사용할 수 있습니다.

List<int> nums = new(){ 1, 2, 3, 4, 5 };
Predicate<int> isEven = x => x % 2 == 0; // 짝수놈들만

int firstEven = nums.Find(isEven); // 2, 첫번째 짝수
var evens     = nums.FindAll(x => x % 2 == 0); // [2,4] 모든 짝수들

 

Func<TIn, TOut> 이런식으로 작업할 수도 있습니다.

 

Func<int, string> toText = n => $"#{n}";
string s = toText(7); // "#7"

 

 

코딩하다보면 상당히 자주 쓰이는 구문(시그니처) 들이므로 눈에 익혀두면 좋습니다.

 


 

그럼 오늘도 좋은 하루 보내세요~

안뇽 ~ (˶˃ᆺ˂˶)