본문 바로가기
C#

[C#] Action, Func, Predicate 제네릭 대리자(델리게이트; Delegate)와 매개변수에 메서드 전달

by RucA 2024. 4. 26.
728x90
반응형

닷넷 API에 내장된 제네릭 대리자인  Action, Func, Predicate를 정리해보자

 

대리자 요약
Action 반환값이 없는 메서드를 대신 호출
Func 매개변수와 반환값이 있는 메서드를 대신 호출
Predicate 매개변수에 대한 bool 값을 반환하는 메서드를 대신 호출

 

 

Action<T> 대리자


반환값이 없는 메서드를 대신 호출하는 제네릭 대리자로 주로 출력 등과 엮어서 사용할 수 있다.

 

class DelegatePractice
{
    static void Main()
    {
        //Action 대리자 생성 : 반환값이 없으므로 인자는 모두 매개변수
        Action<string> printf = Console.Write;
        Action<int, int> printAdd = (int a, int b) => Console.WriteLine(a + b);
    
        //대리자를 통한 호출
        printf("Hello Action!\n");
        printAdd(3, 6);
    }
}
//출력 : Hello Action! 9

 

Action 제네릭 대리자를 활용해 C의 printf를 만들어보았다. 반환값이 없는 메서드를 대상으로 하기에 Action의 인자는 모두 매개변수의 타입이라고 볼 수 있다.

 

 

Func<T> 대리자


Func<매개변수 형식, 반환값 형식>로 매개변수와 반환값 형식이 있는 메서드를 대신 호출할 수 있다.

 

class DelegatePractice
{
    static void Main()
    {
        //Func 대리자 생성 : 가장 마지막 인자는 반환값의 타입
        Func<double, double> sqrt = Math.Sqrt;
        //대리자를 통한 호출
        Console.WriteLine(sqrt(4));

        //첫번째, 두번째 인자는 매개변수의 타입을 나타낸다
        Func<int, int, int> max = Math.Max;
        //대리자를 통한 호출
        Console.WriteLine(max(3,9));
        
        //이미 있는 메서드 이외에도 무명 메서드(지난 포스팅 참고)와 람다 식으로 만들 수 있다.
        Func<int, double> lambda = x => x * 1.5f;
        //대리자를 통한 호출
        Console.WriteLine(lambda(3));
    }
}
//출력 : 2 9 4.5

 

매개변수가 2개일 경우, Func<매개변수1 타입, 매개변수2 타입, 반환값 타입>이다. Func<T>를 사용하면 별다른 델리게이트 선언 없이도 곧바로 람다식을 활용한 함수를 이용할 수 있다.

 

 

Predicate<T> 대리자 


매개변수로 타입을 받아서 특정한 로직을 수행한 후 결과를 bool형으로 반환하는 메서드를 대신 호출한다.

 

class DelegatePractice
{
    static void Main()
    {
        //Predicate 제네릭 대리자 생성
        Predicate<string> isNullOrEmpty = String.IsNullOrEmpty;
        //대리자를 통한 호출
        Console.WriteLine(isNullOrEmpty(null));
        
        //Predicate 제네릭 대리자를 메서드의 매개변수 형식으로 활용 가능
        static string checkNum (Predicate<int> target)
        {
            for(int i = 1; i<50; i++)
            {
                if (target(i)) return $"Checked : {i}";
            }
            return "Nothing Checked";
        }
        
        //대리자 인자로 람다식을 통한 조건을 부여 가능
        var checkStr = checkNum(v => v % 37 == 0);
        Console.WriteLine(checkStr);
    }
}
//출력 : True Checked : 37

 

위의 예제처럼 Predicate<T> 제네릭 대리자는 매개변수에 대리자 형식을 사용하는 것으로, 원하는 조건을 인자로 기입할 수 있도록 해준다. 이는 메서드의 매개변수를 확장해서 람다식을 인자로 받아들일 수 있게 해준다. Func<T> 제네릭 대리자 또한 매개변수의 형식으로 지정할 수 있으며, 이를 활용하는 것으로 메서드의 매개변수로 람다식을 받아 계산한 후 출력하는 유연한 메서드를 만들 수 있다.

 

 

매개변수에 메서드 전달하기


람다 식을 인자로 받는 대리자 형식을 매개 변수로 사용하는 것으로, 좀 더 유연한 메서드를 작성할 수 있다. 람다식은 물론 이미 작성된 메서드 역시 인자로 받을 수 있다.

 

class DelegatePractice
{
    static void Main()
    {
        //매개변수 형식으로 Func<T> 제네릭 대리자 형식을 지정
        void Calc(int a, int b, Func<int, int, int> calc) => Console.WriteLine(calc(a, b));
        
        //람다식과 혼합해 사용하는 것으로 좀 더 유연한 메소드가 만들어졌다
        Calc(2, 7, (a, b) => a + b);
        Calc(5, 6, (a, b) => a * b);

        //람다식을 사용하지 않는 메소드
        int Minus(int a, int b)
        {
            return (a > b) ? a - b : b - a;
        }
        
        //다른 메서드 역시 인자로 받아진다.
        Calc(1, 9, Minus);
    }
}
//출력 : 9 30 8
728x90
반응형