코딩/C#

[C#] 대리자

Hun die 2022. 8. 10. 16:11
대리자

 

- 대리자는 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