C#에서 대리자는 콜백(Callback)을 구현하기 위해 사용됩니다.
콜백이란 어떤 일을 해줄 코드를 만들고, 이 코드가 실행할 이벤트 코드는 컴파일 시점이 아닌 프로그램이 실행 중인 시점에 부여하는 식입니다.
객체의 주소를 가리키는 "참조"를 제가 전 게시물에서 소개한 적이 있을 겁니다.
대리자는 메소드에 대한 참조입니다.
대리자에 메소드의 주소를 할당한 후 대리자를 호출하 이 대리자가 메소드를 호출해 줍니다.
즉, 대리자(Delegate)는 메소드를 참조하는 객체입니다. 대리자는 메소드를 변수에 할당하거나 매개변수로 전달하거나 반환값으로 사용할 수 있습니다.
대리자는 델리게이트 타입을 선언하여 사용합니다. 델리게이트 타입은 반환형과 매개변수를 지정하여 선언합니다. 예를 들어, int를 반환하고 int 매개변수를 하나 갖는 대리자를 선언하려면 다음과 같은 코드를 작성할 수 있습니다.
delegate int Calculate(int x);
실제로 선언해놓고 보니 더더욱 메소드와 비슷해 보입니다.
여기서 제가 C#을 책으로 한 번 정독하면서 대리자에 대해 잘 이해 안 되고 무슨 소리인지 몰랐는데 다시 한번 블로그로 정리하면서 공부하니까 제가 놓쳤던 부분을 알았습니다.
대리자는 형식입니다!!! Type!!! int, string과 같은 형식이며 "메소드를 참조하는 무엇"을 만들려면 대리자의 인스턴스를 따로 만들어야 한다는 것입니다.
저는 대리자가 형식이라는 부분을 잘 인식하지 못하고 지나쳐 대리자를 이용해 콜백을 구현하는 과정을 머리로 잘 이해가 안 되었습니다.
여기서 미리 요약해서 구현 과정을 쓰자면
- 대리자를 선언
- 대리자의 인스턴스를 생성하고, 인스턴스를 생성할 때는 대리자가 참조할 메소드를 매개 변수로 넘김(맨날 헷갈려서 강조함)
- 대리자를 호출
이제 이 과정을 코드로 보겠습니다.(o ゜▽゜) o☆
using System;
namespace Delegate
{
//대리자 선언
delegate int MyDelegate( int a, int b);
class Calculator
{
//Plus()와 Minus() 메소드 모두 MyDelegate 대리자의 반환 형식과 매개 변수를 따릅니다.
public int Plus(int a, int b)// 대리자는 인스턴스 메소드도 참조할 수 있습니다.
{
return a + b;
}
public static int Minus(int a, int b)// 대리자는 정적 메소드도 참조할 수 있습니다.
{
return a - b;
}
}
class MainApp
{
static void Main(string[] args)
{
Calculator Calc = new Calculator();
MyDelegate Callback;
//대리자를 메소드 호출하는것과 같이 사용하고,
//매개변수로 참조하고 있는 메소드를 넣어주면 참조하고 있는 메소드가 실행됩니다.
Callback = new MyDelegate( Calc.Plus );
Console.WriteLine(Callback(3, 4));
Callback = new MyDelegate(Calculator.Minus);
Console.WriteLine(Callback(7, 5));
}
}
}
프로그래밍을 하다 보면 "값"이 아닌 "코드" 자체를 매개 변수로 넘기고 싶을 때가 많습니다.
대리자는 메소드에 대한 참조입니다.
그러므로 메소드의 매개 변수로 다른 메소드를 참조할 수 있는 대리자를 넣을 수 있습니다.
전체 코드를 보며 주석으로 설명하겠습니다.
using System;
namespace UsingCallback
{
//첫번째로 대리자를 선언해주고
delegate int Compare(int a, int b);
class MainApp
{
//두번째로 Compare 대리자가 참조할 비교 메소드를 작성합니다.
static int AscendCompare(int a, int b)
{
if (a > b)
return 1;
else if (a == b)
return 0;
else
return -1;
}
static int DescendCompare(int a, int b)
{
if (a < b)
return 1;
else if (a == b)
return 0;
else
return -1;
}
//세번째로 정렬할 배열과 비교 메소드를 참조할 대리자를 매개 변수로 받는 정렬 메소드를 작성합니다.
//이렇게 작성하면 버블정렬을 오름차순으로 할건지 아니면 내림차순으로 할건지는 이 정렬 메소드를 사용하는
//프로그래머가 결정할수 있게 됩니다.
static void BubbleSort(int[] DataSet, Compare Comparer)
{
int i = 0;
int j = 0;
int temp = 0;
for (i = 0; i < DataSet.Length - 1; i++)
{
for (j = 0; j < DataSet.Length - (i + 1); j++)
{
if (Comparer(DataSet[j], DataSet[j + 1]) > 0)
{
temp = DataSet[j + 1];
DataSet[j + 1] = DataSet[j];
DataSet[j] = temp;
}
}
}
}
static void Main(string[] args)
{
int[] array = { 3, 7, 4, 2, 10 };
Console.WriteLine("Sorting ascending...");
//네번째로 정렬 메소드를 호출하면 우리가 원하던 대로 정렬 방식이 우리가 정할 수 있는 정렬 코드를 얻을 수 있습니다.
//이런 식으로 매개변수를 적어야하는 메소드가 있으면
//앞으로 대리자를 이용해 만들어진 라이브러리 함수인것 같은데 라고 예상할 수 있습니다.
BubbleSort(array, new Compare(AscendCompare));
for (int i = 0; i < array.Length; i++)
Console.Write($"{array[i]} ");
int[] array2 = { 7, 2, 8, 10, 11 };
Console.WriteLine("\nSorting descending...");
BubbleSort(array2, new Compare(DescendCompare));
for (int i = 0; i < array2.Length; i++)
Console.Write($"{array2[i]} ");
Console.WriteLine();
}
}
}
'C# 프로그래밍' 카테고리의 다른 글
[C#] 문 형식의 람다식 (0) | 2023.03.06 |
---|---|
[C#] 익명 메소드와 람다식 (0) | 2023.02.28 |
[C#] C#에서 예외 처리 구현 간단하게 (0) | 2023.02.27 |
[C#] foreach가 가능한 객체 만들기 (0) | 2023.02.24 |
[C#] 인덱서 (0) | 2023.02.24 |