C#/TIL(Today I Learned)

2025-04-26 <Action과 Func와 람다 함수>

프린스 알리 2025. 4. 26.

 

Func와 Action의 차이점

Func와 Action은 C#에서 제공하는 델리게이트 타입이다.

델리게이트는 메서드를 참조하는 타입으로, 코드를 외부로부터 받아 실행할 수 있게 해준다.

두 타입은 구조는 비슷하지만 반환값 유무에 따라 역할이 다르다.

Func

  • 반환값이 있는 델리게이트다.
  • 기본 형태는 Func<in T1, ..., out TResult>이다.
  • 매개변수들을 입력받아, 마지막 타입으로 명시된 반환값을 리턴한다.

예시:

Func<int, int, int> add = (a, b) => a + b;
int result = add(3, 4); // result = 7

위는 int 두 개를 받아서 int 하나를 반환하는 Func이다.

Action

  • 반환값이 없는 델리게이트다.
  • 기본 형태는 Action<in T1, ...>이다.
  • 입력받은 매개변수로 작업만 수행하고 반환값은 없다.

예시:

Action<string> greet = name => Console.WriteLine($"Hello, {name}!");
greet("Alice"); // 콘솔에 "Hello, Alice!" 출력

이 코드는 문자열을 입력받아 인사 메시지를 출력하지만 아무것도 반환하지 않는다.

Func를 이용하여 람다를 받아 실행하는 예제

다음은 Func를 사용하여 외부에서 람다를 전달받아 실행하는 예제이다.

using System;

class Program
{
    static Func<int, int> _sessionFactory;

    static void Main(string[] args)
    {
        _sessionFactory = x => x * x;  // 입력값의 제곱을 반환하는 람다 대입
        ExecuteDynamicFunc();

        _sessionFactory = x => x + 10; // 입력값에 10을 더하는 람다로 교체
        ExecuteDynamicFunc();
    }

    static void ExecuteDynamicFunc()
    {
        int input = 5;
        int result = _sessionFactory.Invoke(input);
        Console.WriteLine($"입력: {input}, 결과: {result}");
    }
}

출력 결과:

입력: 5, 결과: 25
입력: 5, 결과: 15

설명

  • Func<int, int> 타입을 가진 _sessionFactory 필드를 만든다.
  • 외부(Main)에서 원하는 로직을 람다 식으로 주입한다.
  • ExecuteDynamicFunc 메서드에서는 _sessionFactory.Invoke(input)를 통해 주입된 함수를 실행한다.

Func 확장 예제: 매개변수가 여러 개인 경우

두 개의 숫자를 입력받아 결과를 반환하는 경우에도 같은 패턴을 사용할 수 있다.

using System;

class Program
{
    static Func<int, int, int> _sessionFactory;

    static void Main(string[] args)
    {
        _sessionFactory = (x, y) => x + y; // 덧셈
        ExecuteDynamicFunc();

        _sessionFactory = (x, y) => x * y; // 곱셈
        ExecuteDynamicFunc();
    }

    static void ExecuteDynamicFunc()
    {
        int a = 3;
        int b = 7;
        int result = _sessionFactory.Invoke(a, b);
        Console.WriteLine($"입력: {a}, {b}, 결과: {result}");
    }
}

출력 결과:

입력: 3, 7, 결과: 10
입력: 3, 7, 결과: 21

설명

  • _sessionFactory에 (int, int) => int 형태의 람다를 주입한다.
  • 원하는 연산(덧셈, 곱셈 등)을 외부에서 유연하게 변경할 수 있다.

Action 확장 예제: 반환값 없이 작업만 수행하는 경우

반환값이 필요 없다면 Action을 사용할 수 있다.

using System;

class Program
{
    static Action<int, int> _sessionFactory;

    static void Main(string[] args)
    {
        _sessionFactory = (x, y) => Console.WriteLine($"{x} + {y} = {x + y}");
        ExecuteDynamicAction();
    }

    static void ExecuteDynamicAction()
    {
        int a = 4;
        int b = 5;
        _sessionFactory.Invoke(a, b);
    }
}

출력 결과:

4 + 5 = 9

 


Func 비동기 확장 예제: 비동기로 동작하는 경우

Func는 Task를 반환하는 비동기 함수도 받을 수 있다.

using System;
using System.Threading.Tasks;

class Program
{
    static Func<int, Task<int>> _sessionFactory;

    static async Task Main(string[] args)
    {
        _sessionFactory = async x =>
        {
            await Task.Delay(500); // 0.5초 대기
            return x * 2;
        };
        await ExecuteDynamicFuncAsync();
    }

    static async Task ExecuteDynamicFuncAsync()
    {
        int input = 5;
        int result = await _sessionFactory.Invoke(input);
        Console.WriteLine($"입력: {input}, 결과: {result}");
    }
}

출력 결과:

입력: 5, 결과: 10

 

'C# > TIL(Today I Learned)' 카테고리의 다른 글

2025-05-06 <클래스를 전역에서 접근하고 싶을 때>  (0) 2025.05.06
2025-04-26 <형변환>  (0) 2025.04.26
2025-04-24 <박싱과 언박싱>  (0) 2025.04.24
2025-04-23 <const와 readonly>  (0) 2025.04.23
2025-04-19 <ArraySegment>  (0) 2025.04.19

댓글