C# Delegate


Delegate는 인자만 맞으면 실행되게 하는 대신 실행 시켜주는 Managed C# point 역할을 하는 특별한 객체이다. 이번 포스트에서는 묶여진 Delegation을 풀어 따로 결과값을 받아 오는 방안에 대해서 알아 보도록 하겠다.

아래와 같이 메소드를 등록(간단하게 Action 으로 진행)하고 마지막에 인자를 넘겨 실행 시키면 전체 연결된 체인 메소드가 실행이 된다.

            TestDelegate testDelegate = null;
 
            testDelegate += (ab=> { return (a + b); };
            testDelegate += (ab=> { return (a - b); };
            testDelegate += (ab=> { return (a / b); };
            testDelegate += (ab=> { return (a * b); };
 
            Debug.WriteLine(testDelegate(1020));

하지만 위와 같이 실행하면 각각의 결과에 대한 값이 나오는 것이 아니라 최종 마지막에 실행될 '*' 연산 결과에 대해서만 화면에 뿌려주게 된다. 전에 실행된 결과값은 메모리상에서 사라지게 되는 것이다.

이번에는 위와 같이 체인으로 묶여 있어도 각각의 결과값에 대해서 사용할 수 있도록 만든 메소드를 소개 하겠다.
        /// <summary>

        /// MulticastDelegate를 이용해 여러 메소드를 실행 할 때 각각의 반환값을 받아 온다.         /// </summary>         /// <typeparam name="T">return object type</typeparam>         /// <param name="func">Delegate[]를 반환하는 Func</param>         /// <param name="args">delegate가 실행에 필요한 인자 값</param>         /// <returns>delegate가 실행되고 반환된 리턴값들</returns>         /// <remarks>         /// 동적인 delegate의 결과값을 IEnumerable<T>로 받아 오기         /// </remarks>         /// <exception cref="ArgumentNullException">         /// Null 을 넘겨 주면 발생         /// </exception>         /// <exception cref="InvalidCastException">         /// Generic가 제대로 선언되지 않으면 발생         /// </exception>         /// <example>         /// delegate int TestDelegate(int a, int b);         /// TestDelegate testDelegate = null;         /// testDelegate += (a, b) => { return (a + b); };         /// testDelegate += (a, b) => { return (a - b); };         /// testDelegate += (a, b) => { return (a / b); };         /// testDelegate += (a, b) => { return (a * b); };         /// GetDelegateInvokeResults<int>(() => delegate.GetInvocationList(), 1, 2);   //호출시 generic 방법으로 반환될 형식을 정의 함.         /// </example>                  public IEnumerable<T> GetDelegateInvokeResults<T>(Func<Delegate[]> funcparams object[] args)         {                          List<T> list = new List<T>();             //인자로 받은 Func를 실행한다.             var delList = func.Invoke();             //Delegate[]를 loop             foreach (var del in delList)             {                 //동적 인자로 실행하고 반환값을 List에 넣는다.                 list.Add((T)del.DynamicInvoke(args));             }             return list;         }

delegate를 동적으로 컨트롤 하기 위해서 Func와 params 라는 개념을 도입을 하여 메소드를 만들었다.


위 메소드를 아래와 같이 사용하여 results에 담아 올 수 있다.

TestDelegate testDelegate = null;         testDelegate += (ab=> { return (a + b); };         testDelegate += (ab=> { return (a - b); };         testDelegate += (ab=> { return (a / b); };         testDelegate += (ab=> { return (a * b); };         var results = GetDelegateInvokeResults<int>(() => testDelegate.GetInvocationList(), 1020);

이렇게 되면 결과값을 가지고 지지고 볶을 수 있을 것이다.


다음에 기회가 된다면 일률적인 값으로 파라메터를 넘기는 것이 아닌 각각의 delegate마다 다른 파라메터를 넘길 수 있는 방안을 알아 보도록 하겠다.

+ Recent posts