2016년 12월 6일 화요일

대리자(Delegate), 무명 메서드(Anonymous Method), 람다식(Lambda)

개인적으로 대충 정리한 내용입니다. 자세한 내용은 MSDN 링크를 참고하세요.

대리자(Delegate)

: https://msdn.microsoft.com/ko-kr/library/ms173171.aspx

대리자는 특정 매개 변수 목록 및 반환 형식이 있는 메서드에 대한 참조를 나타내는 형식입니다.
 
    public delegate int PerformCalculation(int x, int y);


  • 대리자는 C++의 함수 포인터와 유사하지만 형식이 안전합니다.
  • 대리자를 통해 메서드를 매개 변수로 전달할 수 있습니다.
  • 대리자를 사용하여 콜백 메서드를 정의할 수 있습니다.
  • 여러 대리자를 연결할 수 있습니다. 예를 들어 단일 이벤트에 대해 여러 메서드를 호출할 수 있습니다.
  • 메서드와 대리자 형식이 정확히 일치할 필요는 없습니다. 자세한 내용은 대리자의 가변성 사용을 참조하십시오.
  • C# 버전 2.0에는 별도로 정의된 메서드 대신 코드 블록을 매개 변수로 전달할 수 있도록 하는 무명 메서드라는 개념이 도입되었습니다. C# 3.0에는 인라인 코드 블록을 더 간단하게 작성할 수 있는 람다 식이 도입되었습니다. 특정 컨텍스트에서는 무명 메서드와 람다 식 모두 대리자 형식으로 컴파일됩니다. 이 두 기능을 익명 함수라고 합니다. 람다 식에 대한 자세한 내용은 익명 함수를 참조하십시오.
대리자 조합(멀티캐스트 대리자)
: https://msdn.microsoft.com/ko-kr/library/ms173175.aspx

이 예제에서는 멀티캐스트 대리자를 만드는 방법에 대해 설명합니다. 대리자 개체에는 + 연산자를 사용하여 대리자 인스턴스에 여러 개체를 할당할 수 있는 유용한 특성이 있습니다. 멀티캐스트 대리자에는 할당된 대리자 목록이 포함됩니다. 멀티캐스트 대리자를 호출하면 목록에 있는 대리자가 순서대로 호출됩니다. 같은 형식의 대리자만 조합할 수 있습니다.
- 연산자를 사용하면 멀티캐스트 대리자에서 구성 요소 대리자를 제거할 수 있습니다.

using System;

        // Define a custom delegate that has a string parameter and returns void.
        delegate void CustomDel(string s);

        class TestClass
        {
            // Define two methods that have the same signature as CustomDel.
            static void Hello(string s)
            {
                System.Console.WriteLine("  Hello, {0}!", s);
            }

            static void Goodbye(string s)
            {
                System.Console.WriteLine("  Goodbye, {0}!", s);
            }

            static void Main()
            {
                // Declare instances of the custom delegate.
                CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;

                // In this example, you can omit the custom delegate if you 
                // want to and use Action<string> instead.
                //Action<string> hiDel, byeDel, multiDel, multiMinusHiDel;

                // Create the delegate object hiDel that references the
                // method Hello.
                hiDel = Hello;

                // Create the delegate object byeDel that references the
                // method Goodbye.
                byeDel = Goodbye;

                // The two delegates, hiDel and byeDel, are combined to 
                // form multiDel. 
                multiDel = hiDel + byeDel;

                // Remove hiDel from the multicast delegate, leaving byeDel,
                // which calls only the method Goodbye.
                multiMinusHiDel = multiDel - hiDel;

                Console.WriteLine("Invoking delegate hiDel:");
                hiDel("A");
                Console.WriteLine("Invoking delegate byeDel:");
                byeDel("B");
                Console.WriteLine("Invoking delegate multiDel:");
                multiDel("C");
                Console.WriteLine("Invoking delegate multiMinusHiDel:");
                multiMinusHiDel("D");
            }
        }
        /* Output:
        Invoking delegate hiDel:
          Hello, A!
        Invoking delegate byeDel:
          Goodbye, B!
        Invoking delegate multiDel:
          Hello, C!
          Goodbye, C!
        Invoking delegate multiMinusHiDel:
          Goodbye, D!
        */

대리자 사용
: https://msdn.microsoft.com/ko-kr/library/ms173172.aspx

C# 1.0 이상에서는 다음 예제와 같이 대리자를 선언할 수 있습니다.
    // Declare a delegate.
    delegate void Del(string str);

    // Declare a method with the same signature as the delegate.
    static void Notify(string name)
    {
        Console.WriteLine("Notification received for: {0}", name);
    }
    // Create an instance of the delegate.
    Del del1 = new Del(Notify); 

C# 2.0에서는 비슷한 방법을 통해 다음 예제에서와 같이 이전 예제의 선언을 작성할 수 있습니다.
        // C# 2.0 provides a simpler way to declare an instance of Del.
        Del del2 = Notify;
C# 2.0 이상에서는 다음 예제에서와 같이 무명 메서드를 사용하여 대리자를 선언하고 초기화할 수도 있습니다.
        // Instantiate Del by using an anonymous method.
        Del del3 = delegate(string name)
            { Console.WriteLine("Notification received for: {0}", name); };
C# 3.0 이상에서는 다음 예제에서와 같이 람다 식을 사용하여 대리자를 선언하고 인스턴스화할 수도 있습니다.
        // Instantiate Del by using a lambda expression.
        Del del4 = name =>  { Console.WriteLine("Notification received for: {0}", name); };


무명 메서드(Anonymous Method)

: https://msdn.microsoft.com/ko-kr/library/0yw3tz5k.aspx

2.0보다 이전 버전의 C#에서는 명명된 메서드를 사용하는 방법으로만 대리자를 선언할 수 있었습니다. C# 2.0에는 무명 메서드가 도입되었고 C# 3.0 이상에서는 무명 메서드 대신 람다 식을 사용하여 인라인 코드를 작성하는 방법이 더 선호됩니다.
무명 메서드에는 람다 식에 없는 기능이 한 가지 있습니다. 무명 메서드를 사용하면 매개 변수 목록을 생략할 수 있으며, 이는 무명 메서드가 여러 시그니처를 가진 대리자로 변환될 수 있음을 의미합니다. 람다 식을 사용해서는 이렇게 할 수 없습니다. 람다 식에 대한 자세한 내용은 람다 식을 참조하십시오.

        // Create a handler for a click event.
        button1.Click += delegate(System.Object o, System.EventArgs e)
                           { System.Windows.Forms.MessageBox.Show("Click!"); };
    // Create a delegate.
    delegate void Del(int x);

    // Instantiate the delegate using an anonymous method.
    Del d = delegate(int k) { /* ... */ };
무명 메서드를 사용하면 별도의 메서드를 만들 필요가 없으므로 대리자를 인스턴스화하는 데 따르는 코딩 오버헤드를 줄일 수 있습니다.

무명 메서드의 매개 변수 범위는 무명 메서드 블록입니다.
무명 메서드 블록 안에서 블록 밖을 대상으로 goto, break 또는 continue와 같은 점프 문을 사용하면 오류가 발생합니다. 무명 메서드 블록 밖에서 블록 안을 대상으로 goto, break 또는 continue와 같은 점프 문을 사용해도 오류가 발생합니다.
지역 변수 및 매개 변수의 범위에 무명 메서드 선언이 포함되는 경우 이러한 변수를 무명 메서드의 외부 변수라고 합니다. 예를 들어, 다음 코드 단편에서 n은 외부 변수입니다.
        int n = 0;
        Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

람다식(Lambda)

: https://msdn.microsoft.com/ko-kr/library/bb397687.aspx

람다 식은 대리자 또는 식 트리 형식을 만드는 데 사용할 수 있는 익명 함수입니다. 람다 식을 사용하여 인수로 전달되거나 함수 호출 값으로 반환되는 로컬 함수를 쓸 수 있습니다. 람다 식은 LINQ 쿼리 식을 작성하는 데 특히 유용합니다.

람다 식을 만들려면 람다 연산자 => 왼쪽에 입력 매개 변수를 지정하고(있는 경우) 다른 쪽에 식이나 문 블록을 삽입합니다. 예를 들어 람다 식 x => x * x는 이름이 x인 매개 변수를 지정하고 x 제곱 값을 반환합니다. 다음 예제와 같이 대리자 형식에 이 식을 할당할 수도 있습니다.
delegate int del(int i);  
static void Main(string[] args)  
{  
    del myDelegate = x => x * x;  
    int j = myDelegate(5); //j = 25  
}  

식 트리 형식을 만들려면
using System.Linq.Expressions;  
  
namespace ConsoleApplication1  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Expression<del> myET = x => x * x;  
        }  
    }  
}  

=> 연산자는 할당(=)과 우선 순위가 같고 오른쪽 결합성이 있습니다(연산자 문서의 "결합성" 단원 참조).
 무명 메서드에 적용되는 모든 제한은 람다 식에도 적용됩니다. 자세한 내용은 무명 메서드을 참조하세요.

Lambda는 내용이 많아서 생략..

댓글 없음:

댓글 쓰기