본문으로 바로가기

[C#] 델리게이트(Delegate)

category Program/C# 2019. 1. 25. 15:13

환경 : Visual Studio 2015


1. 델리게이트 (Delegate)




해석하면 '대리인'이라는 뜻의 델리게이트는 메소드를 참조하는 변수이다. 

C++의 함수 포인터와 비슷하기 때문에 C++을 공부한 사람이라면 어렵지 않게 이해하겠지만, 

그렇지 않은 사람들을 위해 간단히 개념을 설명해본다.


델리게이트는 메소드를 대신해서 호출하는 역할을 한다. (메소드의 대리인)

지금까지는 특정 메소드를 처리할 때 그 메소드를 직접 호출해서 실행시켜야 했지만,

델리게이트를 사용하면 그 메소드를 대신하여 호출할 수 있다. 


그럼 이제 델리게이트가 코드상에서 어떻게 쓰이는지 구체적으로 살펴보자.




2. 델리게이트 선언과 참조




델리게이트로 특정 메소드를 대신 호출하기 위해서는 

(1) 우선 그 메소드와 동일한 타입의 델리게이트 타입을 선언해야 한다.


//delegate 반환 타입 델리게이트 이름(매개변수);


메소드 타입은 매개변수와 반환타입에 의해 결정되기 때문에, 

델리게이트 타입도 그 메소드와 동일한 매개변수, 반환타입으로 선언해주면 된다.

(2) 그리고 선언한 델리게이트 타입으로 델리게이트 변수를 생성하고,

생성한 델리게이트 변수에 해당 메소드를 참조시킨다.


// delegate 변수 생성

typeA delegate0;

typeB delegate1;

typeC delegate2;

typeD delegate3;


//메소드 참조

delegate0 = new typeA( funcA );

delegate1 = new typeB( funcB );

delegate2 = new typeC( funcC );

delegate3 = new typeD( funcD );



여기까지하면 이제 델리게이트 변수로 해당 함수를 호출할 수 있게 된다.

그럼 직접 프로그램을 작성해 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public static int Plus(int a, int b) { return a + b; }
    public static int Minus(int a, int b) { return a - b; }
 
    static void Main(string[] args)
    {
        MyDelegate calculate;
 
        calculate = new MyDelegate(Plus);
        int sum = calculate(1122);
        Console.WriteLine("11 + 22 = {0}", sum);
 
        calculate = new MyDelegate(Minus);
        Console.WriteLine("11 - 22 = {0}", calculate(2211));
    }
cs



3. 콜백메서드




사실 위의 예제와 같이 델리게이트를 쓰는것은 큰 의미가 없다.

메소드를 직접 호출하면 되지, 굳이 델리게이트로 참조해서 쓸 필요가 없기 때문이다.

델리게이트의 진정한 가치는 콜백메서드 를 구현할 때에 나타난다.

콜백(Callback)이란 A라는 메서드를 호출할 때에 B라는 메서드를 넘겨주어 

A 메서드로 하여금 B 메서드를 호출하도록 하는 것을 말하며, 이때의 A 메서드를 콜백메서드라 한다.


이 과정에서 델리게이트는 B메서드를 참조하는 변수로써 A메서드에게 넘겨지는 매개변수가 되고,

A메서드는 매개변수로 받은 델리게이트로 B 메서드를 호출한다.


다음 예제를 보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        public static void Calculator(int a, int b, MyDelegate dele)
        {
            Console.WriteLine(dele(a, b));
        }
        public static int plus(int a, int b) { return a + b; }
        public static int minus(int a, int b) { return a - b; }
        public static int multiply(int a, int b) { return a * b; }
        static void Main(string[] args)
        {
            MyDelegate Plus = new MyDelegate(plus);
            MyDelegate Minus = new MyDelegate(minus);
            MyDelegate Multiply = new MyDelegate(multiply);
            Calculator(1122, plus);
            Calculator(3322, minus);
            Calculator(1122, multiply);
        }
cs



위의 예제를 보면 계산기 함수를 호출할 때마다 원하는 연산(메소드)를 넘겨주어

계산기가 해당 기능을 하도록 하고 있다. 


이렇게 특정 함수가 그때그때마다 지정된 기능을 하도록 하는 것.

이것이 콜백 메소드의 알음다움(?)이며, 이는 델리게이트가 있기에 가능한 것이다.



4. 일반화 델리게이트




위에서 작성한 예제에서는 델리게이트가 참조할 수 있는 메소드가 int형뿐이었다.

하지만 델리게이트를 일반화하면 어떤 타입의 메소드든지 참조할 수 있다.


다음 예제를 보자.


어떤 타입의 plus 메소드든지 참조할 수 있도록 델리게이트를 일반화하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  delegate T MyDelegate<T>(T a, T b);
    class Program
    {
        public static void Calculator<T>(T a, T b, MyDelegate<T> dele)
        {
            Console.WriteLine(dele(a, b));
        }
        public static int plus(int a, int b) { return a + b; }
        public static float plus(float a, float b) { return a + b; }
        public static double plus(double a, double b) { return a + b; }
 
        static void Main(string[] args)
        {
            MyDelegate<int> Plus_int = new MyDelegate<int>(plus);
            MyDelegate<float> Plus_float = new MyDelegate<float>(plus);
            MyDelegate<double> Plus_double = new MyDelegate<double>(plus);
 
            Calculator(1122, Plus_int);
            Calculator(3.3f, 2.2f, Plus_float);
            Calculator(5.56.6, Plus_double);
        }
    }
cs



5. 델리게이트 체인




지금까지의 델리게이트는 하나의 델리게이트에 하나의 메소드만을 참조하였다.

하지만 델리게이트는 놀랍게도 여러개의 메소드를 참조할 수 있는 능력자이다.

델리게이트가 여러개의 메소드를 참조하게 하는 방법은 아주 간단하다.

다음과 같이 +, += 로 새로운 메소드를 추가만 해주면 된다.


MyDelegate del;

del = new MyDelegate( func0 );

del += func1;

del += func2;


이제 델리게이트를 호출하면, 참조된 메소드들을 차례대로 호출하게 된다. 

이렇게 하나의 델리게이트에 여러개의 메소드를 연결시키는 것을 델리게이트 체인이라 한다.

그리고 델리게이트에 연결된 메소드를 끊기 원한다면 반대로 -= 를 해주면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    delegate void MyDelegate();
 
    class MainApp
    {
        public static void func0() { Console.Write("첫번째");  }
        public static void func1() { Console.Write("두번째"); }
        public static void func2() { Console.Write("세번째"); }
 
        static void Main(string[] args)
        {
            MyDelegate dele;
            dele = new MyDelegate(func0);
            dele += func1;
            dele += func2;
 
            dele();
            Console.WriteLine();
 
            dele -= func0;
            dele -= func2;
 
            dele();
            Console.WriteLine();
        }
    }
cs


ref : https://mrw0119.tistory.com/19?category=585887




'Program > C#' 카테고리의 다른 글

[C#] .NET 용어 요약  (0) 2019.01.28
[C#] 람다식(Lamdba Expressions)  (0) 2019.01.25
[C#] 프로퍼티 ( Property )  (0) 2019.01.25
[C#] 박싱과 언박싱  (0) 2019.01.24
[C#] Task 클래스  (0) 2019.01.24