대리자는 C 및 C++의 함수 포인터와 유사하게 메서드를 안전하게 캡슐화하는 형식입니다. C 함수 포인터와 달리 대리자는 개체 지향적이고 형식이 안전하며 안전합니다. 다음 예제에서는 Callback
을 인수로 사용하고 void를 반환하는 메서드를 캡슐화할 수 있는 명명 된 대리자를 선언합니다.
public delegate void Callback(string message);
대리자 개체는 일반적으로 대리자가 래핑하는 메서드의 이름을 제공하거나 람다 식을 사용하여 생성됩니다. 대리자는 이러한 방식으로 인스턴스화되면 호출할 수 있습니다. 대리자를 호출하면 대리자 인스턴스에 연결된 메서드가 호출됩니다. 호출자가 대리자에 전달한 매개 변수는 메서드에 전달됩니다. 대리자는 메서드에서 반환 값(있는 경우)을 반환합니다. 다음은 그 예입니다.
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
Console.WriteLine(message);
}
// Instantiate the delegate.
Callback handler = DelegateMethod;
// Call the delegate.
handler("Hello World");
대리자 형식은 .NET의 Delegate 클래스에서 파생됩니다. 대리자 형식은 봉인되고 파생될 수 없으며 사용자 지정 클래스 Delegate를 파생시킬 수 없습니다. 인스턴스화된 대리자는 개체이므로 인수로 전달되거나 속성에 할당될 수 있습니다. 메서드는 대리자를 매개 변수로 수락하고 나중에 대리자를 호출할 수 있습니다. 이를 비동기 콜백이라고 하며 긴 프로세스가 완료되면 호출자에게 알리는 일반적인 방법입니다. 이러한 방식으로 대리자를 사용하는 경우 대리자를 사용하는 코드에는 사용 중인 메서드의 구현에 대한 지식이 필요하지 않습니다. 이 기능은 캡슐화 인터페이스가 제공하는 것과 유사합니다.
콜백의 또 다른 일반적인 용도는 사용자 지정 비교 메서드를 정의하고 정렬 메서드에 해당 대리자를 전달하는 것입니다. 호출자의 코드가 정렬 알고리즘의 일부가 될 수 있습니다. 다음 예제 메서드는 형식을 Callback
매개 변수로 사용합니다.
public static void MethodWithCallback(int param1, int param2, Callback callback)
{
callback("The number is: " + (param1 + param2).ToString());
}
그런 다음 이전 예제에서 만든 대리자를 해당 메서드에 전달할 수 있습니다.
MethodWithCallback(1, 2, handler);
콘솔에 다음 출력을 수신합니다.
The number is: 3
MethodWithCallback
에서는 콘솔을 직접 호출할 필요가 없습니다. 콘솔을 염두에 두고 설계할 필요는 없습니다. 문자열을 준비하고 문자열을 다른 메서드에 전달하는 것입니다 MethodWithCallback
. 위임된 메서드는 임의의 개수의 매개 변수를 사용할 수 있습니다.
인스턴스 메서드를 래핑하기 위해 대리자를 생성하면 대리자는 인스턴스와 메서드를 모두 참조합니다. 대리자는 래핑하는 메서드 외에 인스턴스 형식에 대한 지식이 없습니다. 대리자는 대리자 서명과 일치하는 메서드가 있는 한 모든 형식의 개체를 참조할 수 있습니다. 대리자가 정적 메서드를 래핑하도록 생성되면 메서드만 참조합니다. 다음 선언을 고려합니다.
public class MethodClass
{
public void Method1(string message) { }
public void Method2(string message) { }
}
앞서 표시된 정적 DelegateMethod
와 함께, 이제 Del
인스턴스에서 래핑할 수 있는 세 가지 메서드가 있습니다.
대리자는 호출될 때 둘 이상의 메서드를 호출할 수 있으며, 이를 멀티캐스팅이라고 합니다. 대리자의 메서드 목록(호출 목록)에 추가 메서드를 추가하려면 추가 또는 추가 할당 연산자('+' 또는 '+=')를 사용하여 두 대리자를 추가하면 됩니다. 다음은 그 예입니다.
var obj = new MethodClass();
Callback d1 = obj.Method1;
Callback d2 = obj.Method2;
Callback d3 = DelegateMethod;
//Both types of assignment are valid.
Callback allMethodsDelegate = d1 + d2;
allMethodsDelegate += d3;
호출 allMethodsDelegate
목록에Method1
Method2
DelegateMethod
세 가지 메서드가 포함됩니다. 원래의 세 명의 대리자 d1
, d2
, 그리고 d3
는 변경되지 않은 상태로 유지됩니다.
allMethodsDelegate
호출되면 세 가지 메서드가 모두 순서대로 호출됩니다. 대리자가 참조 매개 변수를 사용하는 경우 참조는 차례로 세 가지 메서드 각각에 순차적으로 전달되고 한 메서드의 변경 내용은 다음 메서드에 표시됩니다. 메서드 중에서 메서드 내에서 catch되지 않은 예외를 throw하면 해당 예외가 대리자의 호출자에게 전달됩니다. 호출 목록에 후속 메서드가 호출되지 않습니다. 대리자의 반환 값 및/또는 out 매개 변수가 있는 경우 마지막으로 호출된 메서드의 반환 값과 매개 변수를 반환합니다. 호출 목록에서 메서드를 제거하려면 빼기 또는 빼기 할당 연산자 (-
또는 -=
)를 사용합니다. 다음은 그 예입니다.
//remove Method1
allMethodsDelegate -= d1;
// copy AllMethodsDelegate while removing d2
Callback oneMethodDelegate = (allMethodsDelegate - d2)!;
대리자 형식은 System.Delegate
에서 파생되므로 해당 클래스에 정의된 메서드와 속성을 대리자에서 호출할 수 있습니다. 예를 들어 대리자의 호출 목록에서 메서드 수를 찾으려면 다음을 작성할 수 있습니다.
int invocationCount = d1.GetInvocationList().GetLength(0);
호출 목록에 여러 메서드가 있는 대리자는 MulticastDelegate의 하위 클래스인 System.Delegate
에서 파생됩니다. 앞의 코드는 두 클래스가 모두 지원 GetInvocationList
되기 때문에 두 경우 모두 작동합니다.
멀티캐스트 대리자는 이벤트 처리에 광범위하게 사용됩니다. 이벤트 원본 개체는 해당 이벤트를 수신하도록 등록된 받는 사람 개체에 이벤트 알림을 보냅니다. 이벤트를 등록하기 위해 받는 사람은 이벤트를 처리하도록 설계된 메서드를 만든 다음 해당 메서드에 대한 대리자를 만들고 대리자를 이벤트 원본에 전달합니다. 이벤트가 발생할 때 소스가 대리자를 호출합니다. 그런 다음 대리자는 받는 사람에서 이벤트 처리 메서드를 호출하여 이벤트 데이터를 전달합니다. 이벤트 원본은 지정된 이벤트에 대한 대리자 형식을 정의합니다. 자세한 내용은 이벤트를 참조 하세요.
컴파일 시간에 할당된 두 가지 형식의 대리자를 비교하면 컴파일 오류가 발생합니다. 대리자 인스턴스가 정적으로 형식 System.Delegate
인 경우 비교가 허용되지만 런타임에 false를 반환합니다. 다음은 그 예입니다.
delegate void Callback1();
delegate void Callback2();
static void method(Callback1 d, Callback2 e, System.Delegate f)
{
// Compile-time error.
Console.WriteLine(d == e);
// OK at compile-time. False if the run-time type of f
// is not the same as that of d.
Console.WriteLine(d == f);
}
참고하십시오
.NET