대리자란 어떤 메서드를 호출하는 방법을 담은 객체이다. 

대리자 기본 사용방법

  c++을 주로하는 사용한 필자는 std::function과 비슷한 개념이라고 이해했다. 

delegate int Transformer(int x);

  위의 예제 구문은 Transformer라는 대리자 형식은 리턴타입이 int이고 매개변수가 int하나를 받는 메서드를

  담을 수 있는 대리자 형식이다. 

static int Square(int x) { return x*x; }

Transformer t = Square;
// Transformer t = new Transformer(Square); 이 문장을 줄여서 쓴 것

int value = t(5);
// int value = t.Invoke(5); 이문장을 줄여서 쓴것 

 

다중 캐스트 대리자

  모든 대리자 인스턴스는 다중 캐스트의 능력이 있다. 

delegate void SomeDelegate();

    class Test
    {
        static void func1() { Console.WriteLine("call func1"); }
        static void func2() { Console.WriteLine("call func2"); }

        public static void Main(String[] args)
        {
            SomeDelegate d = func1;
            // d에 func2를 추가 
            d += func2;

            d();
            
            // d에서 func1을 제거
            d -= func1;
            d();
        }
    }

delegate d에 첫번째 실행때는 func1과 func2가 둘 다 추가 되어서 실행하면 두 메서드 모두 호출된다. 

두번째 호출때는 func1이 빠져서 func2만 호출된다. 

실행결과

또한 대리자의 반환형식이 void가 아니라면 마지막에 호출되는 메서드가 돌려준 값을 받게 됩니다. 

대리자의 대상 메서드가 인스턴스 메서드인 경우

인스턴스 메서드를 대리자에 등록하는 경우 대리자 인스턴스는 메서드의 참조 뿐만 아니라

메서드의 인스턴스에 대한 참조도 알고 있어야 합니다.

namespace ConsoleApp1
{
    delegate void SomeDelegate();
    
    class Test
    {
        public static void Main(String[] args)
        {
            X x = new X();
            SomeDelegate d = x.Func;
            Console.WriteLine(d.Target);        // ConsoleApp1.X
            Console.WriteLine(d.Target == x);   // True
            Console.WriteLine(d.Method);        // void Func()            

            SomeDelegate d2 = X.StaticFunc;

            Console.WriteLine(d2.Target);           // ConsoleApp1.X
            Console.WriteLine(d2.Target == null);   // True
            Console.WriteLine(d2.Method);           // void Func()            

        }
    }

    class X
    {
        public void Func()
        {
            Console.WriteLine("Call X::Func");
        }

        public static void StaticFunc()
        {

        }
    }

}

실행결과

System.Delegate의 Target이 바로 메서드의 인스턴스의 참조값을 가집니다. 

정적메서드인 StaticFunc을 가진 d2의 경우 Target값이 null을 가집니다.

 

표준 Func 대리자와 Action 대리자

C#에서는 표준 제네릭 대리자를 지원하는데 Func과 Action이다.

delegate TResult Func<out TResult>							();
delegate TResult Func<int T, out TResult>					(T arg);
delegate TResult Func<int T1, in T2, out TResult>			(T1 arg1, T2 arg2);
...
// T16까지 지원한다.
// Func은 TResult 타입의 리턴값을 가진다.

delegate void Action						()
delegate void Action<in T>					(T arg);
delegate void Action<in T1, in T2>			(T1 arg1, T2 arg2);
...
// T16까지 지원한다.

Func은 리턴값을 설정할 수 있고 Action은 리턴값이 없다. 최대 16개 인자를 받을 수 있다.

'c#' 카테고리의 다른 글

[c#] 람다 표현식  (0) 2019.09.27
[c#] 이벤트  (0) 2019.09.24

+ Recent posts