콜백 함수는 Windows 프로그래밍의 중요한 부분입니다. C 또는 C++ 프로그래밍 배경이 있다면 많은 Windows API에서 콜백을 사용해 본 적이 있을 것입니다. VB에 AddressOf 키워드를 추가하면 개발자와 개발자는 한때 제한되었던 API를 활용할 수 있습니다. 콜백 함수는 실제로 매우 강력한 프로그래밍 기능인 함수 포인터라고도 알려진 메서드 호출에 대한 포인터입니다. .NET은 대리자 형태로 함수 포인터 개념을 구현합니다. 이들의 특별한 점은 C 함수 포인터와 달리 .NET 대리자는 형식이 안전하다는 것입니다. 이는 C의 함수 포인터가 단지 저장 장치에 대한 포인터일 뿐이라는 것을 보여줍니다. 매개변수와 반환 유형은 말할 것도 없고 이 포인터가 실제로 무엇을 가리키는지도 알 수 없습니다. 이 장에 설명된 대로 .NET 대리자는 형식이 안전한 작업으로 작동합니다. 아래에서는 .NET이 이벤트를 구현하는 방법으로 대리자를 사용하는 방법을 알아봅니다.
1. 위탁
메서드를 다른 메서드에 전달하려면 대리자를 사용해야 합니다. 그 의미를 이해하려면 다음 코드를 살펴보세요.
int i = int.Parse("99");
위의 예에서 볼 수 있듯이 우리는 데이터를 메서드에 매개 변수로 전달하는 데 익숙합니다. 따라서 다른 메소드를 메소드에 전달하는 것은 약간 이상하게 들립니다. 때로는 메서드에 의해 수행되는 작업이 데이터에 대해 수행되지 않고 더 복잡한 다른 메서드에서 수행되기도 합니다. 우리는 컴파일 타임에 두 번째 메소드가 무엇인지 알 수 없습니다. 이 정보는 런타임에만 얻을 수 있으므로 두 번째 메소드를 첫 번째 메소드에 매개변수로 전달해야 합니다. 다음은 몇 가지 예입니다. :
1. 스레드 시작----C#에서는 특정 새로운 실행 시퀀스를 병렬로 실행하도록 컴퓨터에 지시할 수 있습니다. 이 시퀀스를 스레드라고 합니다. 누적된 System.Threading.Thread 인스턴스에서 Start() 메서드를 사용하여 스레드 실행을 시작합니다. 컴퓨터에 새로운 실행 시퀀스를 시작하라고 지시하려면 시퀀스가 실행될 위치를 지정해야 합니다. 실행을 시작하려면 메서드에 대한 세부 정보가 컴퓨터에 제공되어야 합니다. 즉, Thread.Start() 메서드는 스레드에서 호출할 메서드를 정의하는 매개 변수를 가져와야 합니다.
2. 일반 라이브러리 클래스------다양한 표준 작업을 수행하는 코드를 포함하는 라이브러리가 많이 있습니다. 이러한 라이브러리는 일반적으로 자체 포함되어 있습니다. 이런 식으로 라이브러리를 작성할 때 작업을 수행하는 방법을 알게 됩니다. 그러나 때로는 작업에 하위 작업도 포함되는 경우가 있습니다. 라이브러리를 사용하는 클라이언트 코드만이 이러한 하위 작업을 수행하는 방법을 알고 있습니다. 예를 들어, 객체 배열을 가져와서 오름차순으로 정렬하는 클래스를 작성해 보세요. 그러나 정렬 프로세스의 일부에는 배열의 두 개체를 재사용하고 비교하여 어느 개체가 먼저 와야 하는지 확인하는 작업이 포함됩니다. 객체 배열을 정렬할 수 있어야 하는 클래스를 작성하는 경우 객체를 비교하는 방법을 컴퓨터에 미리 알릴 수 없습니다. 클래스의 개체 배열을 처리하는 클라이언트 코드는 정렬할 개체를 비교하는 방법도 클래스에 알려야 합니다. 즉, 클라이언트 코드는 이를 적절하게 만들기 위해 특정 세부 정보를 클래스에 전달해야 합니다.
3. 이벤트 ------ 일반적으로 어떤 이벤트가 발생했는지 코드에 알립니다. GUI 프로그래밍은 주로 이벤트 처리에 관한 것입니다. 이벤트가 발생하면 런타임은 어떤 메서드를 실행해야 하는지 알아야 합니다. 이를 위해서는 시간을 대리자의 매개 변수로 처리하는 메서드를 전달해야 합니다. 이에 대해서는 나중에 논의하겠습니다.
이전에는 메소드 이름이 때때로 다른 메소드에 인수로 전달된다는 규칙을 설정했습니다. 이 프로세스를 완료하는 방법을 아래에 표시해야 합니다. 가장 간단한 방법은 메서드 이름을 매개변수로 전달하는 것입니다. 예를 들어 이전 스레드 예제에서 새 스레드가 시작되고 스레드가 실행을 시작하는 EntryPoint()라는 메서드가 있다고 가정합니다.
무효 진입점()
{
//새 스레드가 수행해야 하는 모든 작업을 수행합니다.
}
다음 코드를 사용하여 새 스레드 실행을 시작할 수도 있습니다.
스레드 NewThread = 새 스레드();
Thread.Start(EntryPoint) //잘못됨
사실 이는 매우 간단한 방식인데, 이는 C나 C++ 등 일부 언어에서 사용되는 방식이다(C와 C++에서는 EntryPoint 매개변수가 함수 포인터이다).
그러나 이러한 직접적인 접근 방식은 유형 안전성과 같은 몇 가지 문제를 일으킬 수 있습니다. 객체 지향 프로그래밍을 수행할 때 메서드는 일반적으로 호출되기 전에 클래스 인스턴스와 연결되어야 합니다. 그리고 이 방법은 이 문제를 고려하지 않습니다. 따라서 .NET Framework에서는 구문상 이러한 직접적인 접근 방식을 허용하지 않습니다. 메서드를 전달하려면 새로운 유형의 개체인 대리자에 메서드의 세부 정보를 캡슐화해야 합니다. 대리자는 단지 특별한 유형의 개체일 뿐입니다. 특별한 점은 이전에 정의한 모든 개체에는 데이터가 포함되어 있지만 대리자는 메서드의 세부 정보만 포함되어 있다는 것입니다.
-