작성날짜 : 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는 델리게이트라고 불리는 타입 안전성 메커니즘을 제공한다.
class MainClass
|
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(1, 2)); Console.WriteLine(fb2(4, 2)); } } } |
위의 예제에서 인스턴스 메서드와 정직인 메서드를 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 |