블로그 이미지
Kanais
Researcher & Developer 퍼즐을 완성하려면 퍼즐 조각들을 하나 둘씩 맞춰나가야 한다. 인생의 퍼즐 조각들을 하나 둘씩 맞춰나가다 보면 인생이란 퍼즐도 완성되는 날이 오려나...?

calendar

1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

Notice

2015. 5. 19. 11:34 Programming/.NET

작성날짜    : 2011-03-28



참고 : http://msdn.microsoft.com/ko-kr/library/ms173171(v=vs.80).aspx

 http://msdn.microsoft.com/ko-kr/library/900fyy8e(v=vs.80).aspx

참고 서적 : 정보문화사 – Jeffrey Richter 저 / 송기수 역 – CLR via C#

 

대리자

대리자는 메서드를 참조하는 형식입니다. 대리자에 메서드가 할당되면 대리자는 이 메서드와 똑같은 방식으로 동작합니다

대리자의 시그니처(반환 형식과 매개 변수로 구성)와 맞는 메서드는 모두 대리자에 할당할 수 있습니다. 이를 통해 프로그래밍 방식으로 메서드 호출을 변경하고 기존 클래스에 새 코드를 삽입할 수 있습니다. 대리자의 시그니처만 알고 있으면 사용자가 작성한 메서드를 대리자에 할당할 수 있습니다.

대리자에서는 이와 같이 메서드를 매개 변수로 취급할 수 있으므로 대리자는 콜백 메서드 정의에 이상적입니다. 예를 들어, 두 개체를 비교하는 메서드에 대한 참조를 정렬 알고리즘에 전달할 수 있습니다. 비교 코드의 분리를 통해 알고리즘을 보다 일반성 있는 방식으로 작성할 수 있습니다.

 

대리자 속성

·         대리자는 C++ 함수 포인터와 유사하지만 형식 안전적입니다.

·         대리자를 통해 메서드를 매개 변수로 전달할  있습니다.

·         대리자를 사용하여 콜백 메서드를 정의할  있습니다.

·         여러 대리자를 연결할  있습니다예를 들어 단일 이벤트에 대해 여러 메서드를 호출할  있습니다.

·         메서드와 대리자 시그니처가 정확히 일치할 필요는 없습니다.

·         C# 버전 2.0에는 별도로 정의된 메서드 대신 코드 블록을 매개 변수로 전달할  있도록 하는 익명 메서드라는 개념이 도입되었습니다.


Delegate

delegate 키워드는 명명된 메서드나 무명 메서드를 캡슐화할  사용할  있는 참조 형식을 선언하는  사용됩니다대리자는 C++ 함수 포인터와 비슷하지만 형식 안전성과 보안성을 제공한다는 점이 다릅니다.

대리자는 이벤트의 기반을 형성합니다.  대리자는 명명된 메서드나 무명 메서드와 연결하여 인스턴스화할 수 있습니다. 명명된 메서드와 함께 사용하려는 경우 허용 가능한 시그니처가 있는 메서드로 대리자를 인스턴스화해야 합니다. 익명 메서드와 함께 사용하는 경우 대리자 및 대리자와 연결된 코드가 함께 선언됩니다.

.NET Framework에서 콜백 함수는 관리되지 않는 Windows 프로그래밍에서와 마찬가지로 매우 유용하며 널리 사용된다. 그러나 .NET Framework는 델리게이트라고 불리는 타입 안전성 메커니즘을 제공한다.


    using
 System;

    delegate
 void SampleDelegate(string message);

 

    class MainClass


    {


        static
 void SampleDelegateMethod(string message)


        {


            
Console.WriteLine(message);


        }


        
static void Main()


        {

            
SampleDelegate d1 = SampleDelegateMethod;


            
SampleDelegate d2 = delegate(string message)


            {


                
Console.WriteLine(message);


            };
          
            d1("Hello");


            d2(
" World");


        }

    }

 

Delegate 선언

 

delegate 타입을 선언한다.

delegate 인스턴스는 Int32 타입의 매개 변수와 void 반환형의 메서드를 참조함.

Internal delegate int MyDele(Int32 value);

 

delegate 키워드를 이용하여 delegate를 선언 하였을 때 내부적으로는 아래와 같은 클래스를 정의한다.

internal class MyDele : System.MulticastDelegate

{

public MyDele(Object object1, IntPtr method); // 생성자

// 지정된 메서드와 동일한 프로토 타입을 가지는 메서드

public virtual void Invoke(Int32 values);

// 비동기 호출을 위한 콜백 메서드

  public virtual IAsyncResult BeginInvoke(Int32 values, AsyncCallback callback,  Object object1);

public virtual void EndInvoke(Int32 values);

}

컴파일러에  의해 정의된 클래스는 4개의 메서드를 가지고 있다. 생성자와 Invoke, BeginInvoke 및 EndInvoke가 바로 그것이다.

 

ILDasm.exe 도구를 이용하여 결과 어셈블리를 살펴보면 컴파일러가 자동으로 생성한 클래스를 확인할 수 있다.


Visual Studio 2008 명령 프롬프트를 이용하여 확인해 보자.

 


 

 

모든 delegate 타입이 MulticastDelegate 타입에서 파생되므로 모든 델리게이트 타입은 MulticastDelegate 타입의 모든 필드와 속성 및 메서드를 상속 받는다. 이 모든 멤버 중에 3개의 non-public 필드가 아마도 가장 중요할 것이다.

필드

타입

설명

_target

System.Object

델리게이트 객체가 정적 메서드를 래핑할 때 이 필드는 null이 되며, 델리게이트 객체가 인스턴스 메서드를 래핑할 때 이 필드는 콜백 메서드에 호출될 객체에 대한 참조를 가지게 된다. 다시 말하면 이 필드는 인스턴스 메서드의 묵시적인 this 매개 변수에 전달될 값을 갖는다.

_methodPtr

System.IntPtr

CLR이 내부적으로 사용하는 콜백 메서드에 대한 포인터

_invocationList

System.object

이 필드는 대부분 null이며, 델리게이트 체인을 생성할 때는 델리게이트의 배열을 참조한다.

 

예제 소스

delegate int Feedback(int vlaue1, int value2);

    class Program

    {

        public int Add(int a, int b)

        {

            return a + b;

        }

        public static int Sub(int a, int b)

        {

            return a - b;

        }

        static void Main(string[] args)

        {

            Program pr = new Program();

            Feedback fb1 = new Feedback(pr.Add);

            Feedback fb2 = new Feedback(Program.Sub);

            Console.WriteLine(fb1(12));

            Console.WriteLine(fb2(42));

}

    }

}

 

위의 예제에서 인스턴스 메서드와 정직인 메서드를 Feedback 매개 변수에 넣어 주었는데, 정적인 메서드인 Sub의 필드 _target이 null이 된다. 인스턴스 메서드인 Add는 pr(Program Instance)의 주소값이 _target에 대입된다.

 

'Programming > .NET' 카테고리의 다른 글

[.NET] Assembly  (0) 2015.05.19
[.NET] 인터페이스 대신 대리자를 사용해야 하는 경우  (0) 2015.05.19
[.NET] is 와 as  (0) 2015.05.19
[.NET] 다형성  (0) 2015.05.19
[.NET] String  (0) 2015.05.19
posted by Kanais