대리자
- 대리자는 C#에서 콜백을 맡아 실행하는 일을 담당하며 deldgate 키워드를 이용해 선언한다.
- 함수를 보관할 수 있는 타입
- Invoke() 메소드로 보관된 모든 함수를 호출할 수 있다.
- '값'이 아닌 '코드'자체를 매개변수에 넘기고 싶을 때 만듭니다.
한정자 delegate 함수();
대리자는 메소드에 대한 참조이기 때문에 자신이 참조할 메소드의 반환 형식과 매개변수를 명시해줘야 합니다.
대리자 선언과 사용 예시
using System;
namespace Delegate
{
delegate int MyDelegate(int a, int b);//대리자 선언
//int(int, int)타입의 함수를 보관 할 수 있는 대리자
//테스트 함수 제작
class Calculator
{
public int PLUS(int a, int b)
{
return a + b;
}
public int MINUS(int a, int b)
{
return a - b;
}
}
//콜백 사용
class MainApp
{
static void Main(string[] args)
{
Calculator _calculator = new Calculator();
MyDelegate Callback;
Callback = new MyDelegate(_calculator.PLUS);
Console.WriteLine(Callback(7, 2));
Callback = new MyDelegate(_calculator.MINUS);
Console.WriteLine(Callback(7, 2));
}
}
}
예시 코드
메소드가 오름차순인지 내림차순인지 대리자를 사용하는 코드
using System;
namespace usingCallback
{
//대리자 생성
delegate int Compare(int a, int b);
class MainApp
{
//대리자가 참조할 비교 메서드 작성
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...");
BubbleSort(array,new Compare(AscendCompare));
// 결과 2 3 4 7 10
for (int i = 0; i < array.Length; i++)
{
Console.Write($"{array[i]} ");
}
Console.WriteLine();
int[] array2 = { 3, 7, 4, 2, 10 };
Console.WriteLine("Sorting...");
BubbleSort(array2, new Compare(DescendCompare));
// 결과 10 7 4 3 2
for (int i = 0; i < array.Length; i++)
{
Console.Write($"{array2[i]} ");
}
Console.WriteLine();
}
}
}
결과 창
코드 분해
1. 대리자 선언
delegate int Compare(int a, int b);
2. 대리자가 참조할 비교 메소드
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;
}
3. 정렬 메소드 작성
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;
}
}
}
}
4. 정렬 메소드 활용
int[] array = { 3, 7, 4, 2, 10 };
BubbleSort(array,new Compare(AscendCompare));
5. 정렬된 값 출력
for (int i = 0; i < array.Length; i++)
{
Console.Write($"{array[i]} ");
}
일반화
위 코드에서 int값 이외에 다른 값도 받아서 사용하기 위해서 일반화<>를 시킬 수 있다.
1. (일반화) 대리자 선언
// 기존 코드
delegate int Compare(int a, int b);
// 바꾼 코드
delegate int Compare<T>(T a, T b);
2. (일반화) 대리자가 참조할 비교 메소드
// 기존 코드
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 int AscendCompare<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b); //자신보다 크면 -1 같으면 0 작으면 1 을 반환합니다.
}
static int DescendCompare<T>(T a, T b) where T : IComparable<T>
{
return a.CompareTo(b) * -1; //* -1을 하면서 자신보다 크면 1 같으면 0 작으면 -1 을 반환합니다.
}
3. (일반화)정렬 메소드
// 기존 코드
static void BubbleSort(int[] DataSet, Compare Comparer)
// 바꾼 코드
static void BubbleSort<T>(T[] DataSet, Compare<T> Comparer)
4. (일반화)정렬 메소드 활용
//기존 코드
int[] array = { 3, 7, 4, 2, 10 };
BubbleSort(array,new Compare(AscendCompare));
// 바꾼 코드
int[] array = { 3, 7, 4, 2, 10 };
BubbleSort<int>(array,new Compare<int>(AscendCompare));
대리자 체인
대리자는 여러개의 메소드를 동시에 참조할 수 있고 참조하기 위한 여러 방법을 소개한다.
먼저 테스트를 위해 간단한 코드를 짜봤다.
delegate void TEST(string STR)// void 함수명(string) 함수를 넣는 대리자를 만듬
void ONE(string str)
{
Console.WriteLine($"1 번 {str}");
}
void TWO(string str)
{
Console.WriteLine($"2 번 {str}");
}
void THREE(string str)
{
Console.WriteLine($"3 번 {str}");
}
1. 연산자 사용
체인 연결 : +, = , +=
// += 를 이용한 체인 연결
TEST number = new TEST( ONE );
number += new TEST( TWO );
number += new TEST( THREE );
// +, = 을 이용한 체인 연결
TEST number = new TEST( ONE ) + new TEST( TWO );
체인 끊기 : -=
// "-=" 를 이용한 체인 끊기
number -= TEST( TWO );
2. 메소드 사용하기
체인 연결 : Deldgate.combine()
// Deldgate.combine() 를 이용한 체인 연결
TEST number = (TEST) Delegate.Combine(
new TEST( ONE ),
new TEST( TWO ),
new TEST( THREE ) );
체인 끊기 : Deldgate.Remove()
// Delegate.Romove 를 이용한 체인 끊기
TEST number = (TEST) Delegate.Romove( ONE ,TWO ,THREE );
호출
연결을 하거나 끊고나서 마지막에 호출을 하면 넣었던 함수들이 순서대로 동작한다.
//메소드 호출
TEST("호출");
'코딩 > C#' 카테고리의 다른 글
[C#] 가비지 컬렉터(Garbage Collection) (0) | 2022.08.12 |
---|---|
[C#] Stream (0) | 2022.08.10 |