포스트

Unity C# Action, Func, Predicate, UnityAction

Action

  • using System 필요
  • 반환 타입이 void인 메소드를 참조하기 위해 사용되는 Delegate

Action의 정의

1
2
3
4
namespace System
{ 
    public delegate void Action(); 
}

오류가 발생하는 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using System;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    private Action _action;

    private void Start()
    {
        _action += () => Debug.Log("asdf");
        _action += Test1;
        
        _action.Invoke();
    }
    
    void Test1(int num1) {}
}
  • _action += Test1; 에서 오류가 발생.
    • Action은 매개변수가 없는 Delegate이기 때문에, 매개변수를 받아 넘기는 것이 불가능.

Action<T>

  • Generic Delegate, 일반화 대리자
  • 매개변수를 사용할 수 있는 Action
  • System 내에 Generic 타입을 최대 15개까지 받을 수 있도록 Action들이 정의.

Action<T>의 정의

1
2
3
4
5
6
7
8
namespace System
{
    public delegate void Action<in T>(T obj);
    public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2, T3 arg3);
    public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
    ...
    public delegate void Action<in T1, in T2, ..., in T15>(T1 arg1, T2 arg2, ... , T15 arg15);
}

예제 코드1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using System;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    private Action<int> action1;
    private Action<int, int> action2;
    private Action<string, string, string> action3;

    private void Start()
    {
        action1 = Test1;
        action2 = Test2;
        action3 = Test3;
        
        action1.Invoke(3);
        action2.Invoke(3, 4);
        action3.Invoke("abc", "def", "ghi");
    }
    
    void Test1(int num1) { Debug.Log(num1); }
    void Test2(int num1, int num2) {Debug.Log(num1 + num2);}
    void Test3(string str1, string str2, string str3) {Debug.Log(str1 + str2+ str3);}
    
}

Func<T, TResult>

  • Generic Delegate, 일반화 대리자
  • Generic 매개변수가 없고, 반환타입만 있는 경우 Func<Result>
  • Generic 매개변수 한개와, 반환타입이 있는 경우 Func<T, Result>
  • Generic 매개변수는 최대 16개까지 사용 가능.
  • Func Delegate Chain에서 여러 함수를 연결한 경우
    • 마지막으로 추가한 함수의 반환 값만을 받음.

Func<T, TResult>의 정의

1
2
3
4
5
6
7
8
namespace System
{
    public delegate TResult Func<out TResult>();
    public delegate TResult Func<in T, out TResult>(T arg);
    public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
    ...
    public delegate TResult Func<in T1,in T2, ...,in T16,out TResult>(T1 arg1, T2 arg2, ..., T16 arg16);
}

예제 코드1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    private Func<int> func;

    private void Start()
    {
        func = () =>
        {
            int num2 = 3;
            Debug.Log(num2);
            return num2;
        };

        func += () =>
        {
            Debug.Log(5);
            return 5;
        };

        int num1 = func.Invoke();
        Debug.Log(num1);
    }
}
  • 위 코드의 실행결과, Console에는 Log로 3, 5, 5만이 출력된다.
  • 이는 int num1 = func.Invoke(); 로 받아온 num15이고, 앞서 func에 추가한 일회용함수의 return num2; 은 사라짐.

예제 코드2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using System;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    // 제네릭 타입의 갯수가 늘면서, 매개변수가 늘어난다.
    private Func<int> func1;
    private Func<int, int> func2;
    private Func<int, int, int> func3;

    private void Start()
    {
        // 람다식으로 간소화
        func1 = () => 1;
        func2 = (num1) => num1;
        func3 = (num1, num2) => num1 + num2;

        int r1 = func1.Invoke();
        int r2 = func2.Invoke(3);
        int r3 = func3.Invoke(4, 5);
        
        Debug.Log(r1);
        Debug.Log(r2);
        Debug.Log(r3);
    }
}

Predicate<T>

  • 반환값이 bool로 고정된 Delegate
  • 매개변수가 존재.
  • 특정 조건을 충족하는지 여부를 검사하는 데 사용됨.
  • 주로 컬렉션의 모든 요소에 대해 조건을 테스트하는데 사용됨.

Predicate<T>의 정의

1
2
3
4
namespace System
{
  public delegate bool Predicate<in T>(T obj);
}

UnityAction

  • Unity Event System에서 사용되는 Delegate
  • using UnityEngine.Events; 필요
  • 매개변수 없음.
  • 주로 UnityEvent<T>와 함께 사용됨.

UnityAction의 정의

1
2
3
4
5
6
7
namespace UnityEngine.Events
{
  /// <summary>
  ///   <para>Zero argument delegate used by UnityEvents.</para>
  /// </summary>
  public delegate void UnityAction();
}

UnityAction<T>의 정의

1
2
3
4
5
6
7
namespace UnityEngine.Events
{
    public delegate void UnityAction<T0>(T0 arg0);
    public delegate void UnityAction<T0, T1>(T0 arg0, T1 arg1);
    ...
    public delegate void UnityAction<T0, T1, T2, T3>(T0 arg0, T1 arg1, T2 arg2, T3 arg3);
}

정리

구분반환값매개변수(인수) 범위용도장점단점
Action없음(void)0개 이상 (일반적으로 최대 16개)1. 반환값 없이 실행할 메서드(람다 표현식 등)를 담는 델리게이트
2. Action<T1, T2, ...> 형태로 매개변수를 받음
1. 반환값이 필요 없는 콜백을 간단히 처리 가능
2. 람다나 메서드를 일관된 방식으로 사용할 수 있음
1. 반환값이 필요한 경우에는 사용 불가
2. 매개변수 개수가 많아지면 가독성이 떨어질 수 있음
Func제네릭으로 지정된 타입0개 이상 (일반적으로 최대 16개)1. 반환값이 있는 메서드(람다 표현식 등)를 담는 델리게이트
2. Func<T1, T2, ... , TResult> 형태로 마지막 타입이 반환값
1. 반환값을 반환받아 로직에서 유연하게 활용 가능
2. 매개변수와 반환값을 명시적으로 표현하여 코드 가독성 향상
1. 반환값이 필요 없는 경우 Func 대신 Action을 쓰는 것이 더 명확
2. 매개변수 개수가 많아지면 복잡도가 증가
Predicatebool (고정)일반적으로 1개1. 조건 판별 목적의 델리게이트(주로 필터링, 검색 등)
2. 매개변수 하나를 받고 bool 결과 반환
1. bool만을 반환하므로 의도가 명확해 가독성 우수
2. 컬렉션 메서드(Find, Exists 등)와 함께 사용 시 직관적
1. bool 외 반환값을 처리할 수 없음
2. 범용도가 Action이나 Func에 비해 제한적
UnityAction없음(void)0개 이상 (일반적으로 최대 16개)1. Unity 이벤트 시스템 전용으로 제공되는 델리게이트
2. 이벤트 등록 시 AddListener/RemoveListener 등에 사용
1. Unity의 이벤트 시스템(UISystem, uGUI 등)에 최적화
2. 시리얼라이즈(Serialize) 가능해서 에디터에서 이벤트 등록이 편리
1. Unity 의존성이 있기 때문에 .NET 일반 프로젝트에서는 별 이점이 없음
2. Action에 비해 특정 환경(유니티)에서만 사용 가능
  • Action: 반환값이 필요 없을 때 사용하는 일반적인 델리게이트.
  • Func: 반환값이 필요할 때 사용하는 델리게이트. 마지막 타입이 반드시 반환형을 의미함.
  • Predicate: bool 반환에 특화된 델리게이트로, 조건 검사 또는 필터링 용도로 주로 사용.
  • UnityAction: Unity 이벤트 시스템 전용 델리게이트로, UnityEvent와 함께 쓰이면 직관적이고 편리함.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.