블로그 이미지
대갈장군

calendar

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 26 27 28 29 30
31

Notice

2010. 6. 17. 23:31 프로그래밍/C#
델리게이트는 C#에 등장하는 새로운 함수 포인터다. 델리게이트의 사전적 의미는 '대표자'라는 의미로 명사일때와 동사일때 발음이 차이가 있으며... 아차차, 주제가 이게 아니지. 이놈의 토플 공부 습관은 사라지지가 않는다. -_-

그렇다면 우선 델리게이트 선언 형식을 살펴보자. 간단하다.

액세스지정자 delegate 리턴타입 이름(인수목록);

이것은 C++에서 사용하는 함수 포인터의 선언 형식보다 훨씬 더 가독성이 좋은 편이다. 

일단, C++과 비교해서 C#의 함수 포인터인 델리게이트의 장점 및 차이점을 나열해 보자.

  • C++의 함수 포인터에 비해 타입 체크가 훨씬 더 엄격하므로 잘못된 대입을 미리 막는다.
  • Delegate는 함수 포인터와 다르게 '클래스 타입'이다. 
  • 인수 목록에 반드시 이름이 필요하다.

  • 사실 위 3가지 차이점 중에 2번이 가장 크고 중요한 차이라고 개인적으로 생각한다. delegate가 클래스 타입이라고 했는데 이는 즉, delegate가 클래스를 선언하는데 사용되는 일종의 명시자라는 말이다. 자, 클래스라면 생성자를 사용해서 객체화를 하여 사용해야 한다. 고로 delegate를 사용하기 위해서는 delegate 클래스 타입으로 임의의 객체의 선언 및 생성자를 이용한 객체화가 요구된다.

    추가로 delegate는 엄연히 독립 타입이므로 어디에나 선언 가능하며 클래스 내부에 선언되면 액세스 지정자 (public, private) 를 줄수가 있다. 만약 외부에 전역으로 선언되면 엑세스 지정자는 굳이 필요하지 않다.

    다음과 두 함수를 보면 인수목록이 같고 리턴 타입이 같으므로 delegate를 쓸수 있다.

    public static void MyFunction1(int input) { Console.WriteLine("MyFunction1" + input); }
    public static void MyFunction2(int input) { Console.WriteLine("MyFunction2" + input); }

    이 두 함수를 가리키기 위해 델리게이트 타입의 클래스를 전역으로 선언한다면 다음과 같이 선언 할 수 있다.

    delegate void MyDele(int a);

    그리고 이제 이 선언된 MyDele 클래스의 객체를 객체화 (생성자를 이용한 구현) 를 하기만 하면 포인터 처럼 바로 사용가능하다.

    MyDele mDele;
    mDele = new MyDele(MyFunction1); //또는 mDele = MyFunction1;
    mDele(50);
    mDele = new MyDele(MyFunction2); //또는 mDele = MyFunction2;
    mDele(100);

    다시 한번 강조하지만 delegate는 클래스 타입이므로 delegate를 사용하기 위해서는 우선 delegate 클래스 타입으로 특정한 리턴 타입과 인수 목록을 가지는 클래스(MyDele)를 생성하고 이 클래스의 객체(mDele)를 생성하여 생성자로 가리킬 함수(MyFunction1 또는 MyFunction2)를 대입하면 만들어진 객체가 바로 그 함수가 된다.

    일단 C++ 방법에 비해 복잡해 보이지만 훨씬 더 '
    세련된
    세련된' 방식이다. 참고로 new로 선언한 후 해제하지 않았는데 우리 뒤에는 항상 Garbage Collector 가 알아서 쓰레기를 수거해 가는 것을 잊지 말자. +.+

    함수 포인터나 델리게이트의 장점은 바로 같은 인수로 리턴 타입을 가지는 여러개의 함수를 돌아가면서 가리킬 수 있다는 것인데 이런 장점은 사실 확 와닿지가 않는다. 이것의 장점을 몸으로 느끼기 위해서는 프로그램이 조금 커야 하며 설계 부터 상속을 염두해두고 만들어야 하며 가상함수들이 즐비해야 비로서 '아~ 이래서 델리게이트가 무려 챕터 하나를 차지하는구나...' 하고 느낄것이다.

    마지막으로 C++의 함수 포인터와 다른 큰 차이점으로 델리게이트는 다른 클래스에 속한 메서드를 가리킬 수 있다는 점이다. C++의 함수 포인터의 경우 임의의 클래스에 선언되어 있을 경우 그 해당 클래스 내부에 있는 메서드 만을 가릴킬 수 있었는데 델리게이트는 그것을 극복했다. 

    이것도 사실 '화악~' 마음에 와 닿지는 않지만 C++의 함수 포인터보다는 훠~얼씬 더 좋다는 것 정도는 알겠다. 

    정리하자면 C++의 함수 포인터는 단순한 변수였다. 말그대로 주소를 저장하는 포인터 였으나 C#에서 등장한 델리게이트라는 놈은 함수 포인터보다 훨씬더 가독성이 좋으며 독립적인 클래스 타입으로써 객체를 생성하여 사용한다는 점이 큰 차이다... 암튼, 당연히 델리게이트가 함수 포인터 보다는 좋다는 이야기지...

    더 많은 이야기를 하고 싶지만 코드가 들어가면 이야기가 너무 길어질 것 같아서 오늘은 여기까지만... 다음엔 공변성과 반공변성에 대해서 토크를 해야 할 듯...



    '프로그래밍 > C#' 카테고리의 다른 글

    Asynchronous programming  (0) 2017.05.31
    C# 이벤트 - 객체 지향적 메시지  (0) 2010.06.25
    C# - 제너릭 (Generic) 에 대한 질문  (0) 2010.06.18
    Covariance and Contravariance  (0) 2010.06.18
    posted by 대갈장군