본문 바로가기

.NET/C#

C# delegate

728x90
반응형

C#를 시작한지 1년이 되가는데요. 그 일년동안 꽤 많은 것을 공부했다고 생각했지만 그 공부한 것들중에서 정말 이해가지 않던것이 있었습니다. 그게 바로 delegate입니다. delegate는 공부하면서도 뭔지는 알겠지만 그것을 꼭 써야하는 이유나 언제 써야하는지는 정말 알지를 못하겠더군요. 제가 asp.net 위주로 공부를 많이하고 실무도 웹쪽을 많이 하다보니 그런것인지 delegate를 쓰질 않게 되더군요.

서론이 조금 길었네요. 그럼 지금부터 정말 델리게이트에 대해서 공부해보겠습니다. 델리게이트는 프로그램에서 어떤 기능을 대신 수행해주는 대리자 역할을 하게됩니다. 델리게이트는 사용자 정의형으로써 클래스와 같은 위치에서 선언되고 선언 형식은 메서드와 동일한 형식으로 선언되죠. 선언 형태는 다음과 같습니다.

    1     delegate string DeleTest(string str);

    2     class Test

    3     {

    4     }
우선 어떻게 사용을 할 수 있는지 알아보도록 하죠.

    1 namespace DelegateTest

    2 {

    3     public delegate void DeleTest();

    4     public delegate int DeleSum(int a, int b);

    5     class Test

    6     {

    7         public void Intro()

    8         {

    9             Console.WriteLine("델리게이트 테스트");

   10         }

   11 

   12         public int Sum(int a, int b)

   13         {

   14             return a + b;

   15         }

   16     }

   17 }

다음과 같이 클래스를 구성하였습니다.  3~4번째 줄을 보면 Test 클래스가 가지고 있는 메소드와 똑같은 형식의델리게이트가 선언되어 있죠. 이렇게 함으로써 실제 메인에서는 델리게이트를 쓸 수 있는 준비작업이 완료되는것입니다.

    1 class Program

    2     {

    3         static void Main(string[] args)

    4         {

    5             Test test = new Test();  //Test클래스 선언 및 인스턴스화

    6             DeleTest output = new DeleTest(test.Intro);

    7             DeleSum sum = new DeleSum(test.Sum);

    8             output();

    9             Console.WriteLine("Sum = {0}", sum(90, 80));

   10         }

   11     }

메인에서는 다음과 같이 구성을 하는데요. 우선 Test클래스를 선언하고 6,7 에서는 델리게이트를 선언 및 인스턴스화를 시킵니다. 만약 DeleTest output = new DeleTest(); 이렇게만 선언을 한다면 컴파일 에러가 발생합니다. 델리게이트는 반드시 메서드를 참조시켜야 한다는 것이죠. 또한 메서드와 델리게이트의 형식이 같아야 됩니다. 만약 다른 델리게이트를 참조시킨다면 역시 에러가 발생하게 되죠 위의 코드를 실행시키게 되면 결과는 다음과 같습니다.

메소드의 호출이 없어도 델리게이트만으로 메소드를 호출한것과 똑같은 결과를 가지고 올 수 있는것이죠. 근데 솔직히 이럴경우에는 그냥 객체 생성후 메소드호출해서 쓰는게 더 효율적일 수 있지요.
지금 예문이 그중에 하나가 아닐까 생각이 드네요. 무엇인가 하면 상품구매에 대한 정보를 이메일과 팩스로 같이 보내는 것입니다. 어떤 상품 구매시 메인에서의 처리와 고객의 이메일과 팩스로 또는 해당 판매처로 이멜과 팩스를 다 보낼때를 생각해서 예문을 만들어 보았습니다. 우선 클래스를 만들어 보았는데요.

    1 delegate void OrderProcessed(OrderProcessedMember order);

    2     class OrderProcessedMember

    3     {

    4         public int OrderNumber { get; set; }

    5         public ArrayList OrderedItems { get; set; }

    6     }

    7 

    8     class OrderManager

    9     {

   10         public OrderProcessed OrderProcess;

   11 

   12         public void ProcessOrder()

   13         {

   14             Console.WriteLine("주문을 정상적으로 처리했습니다.");

   15             if (OrderProcess != null)

   16             {

   17                 ArrayList al = new ArrayList();

   18                 al.Add("컴퓨터");

   19                 al.Add("냉장고");

   20                 al.Add("세탁기");

   21                 OrderProcessedMember order = new OrderProcessedMember

   22                 {

   23                     OrderNumber = 1,

   24                     OrderedItems = al

   25                 };

   26                 OrderProcess(order);

   27             }

   28         }

   29     }

   30     class MailManager

   31     {

   32         public void SendMail(OrderProcessedMember order)

   33         {

   34             Console.WriteLine("고객에게 메일을 전송했습니다.");

   35             Console.WriteLine("주문번호 : " + order.OrderNumber);

   36             Console.Write("주문 내역 : ");

   37             foreach (string item in order.OrderedItems)

   38                 Console.Write(item + "\t");

   39             Console.WriteLine();

   40         }

   41     }

   42     class FaxManager

   43     {

   44         public void SendFax(OrderProcessedMember order)

   45         {

   46             Console.WriteLine("주문정보를 팩스로 전송했습니다.");

   47             Console.WriteLine("주문번호 : " + order.OrderNumber);

   48             Console.Write("주문 내역 : ");

   49             foreach (string item in order.OrderedItems)

   50                 Console.Write(item + "\t");

   51             Console.WriteLine();

   52         }

   53     }

우선 어떤 고객이 컴퓨터, 냉장고, 세탁기를 주문하였다고 가정하였습니다. OrderProcessedMember가 주문번호와 주문상품들을 저장하게 되고요. OrderManager에서 주문 작업을 처리하게 됩니다. 이때 Delegate를 이용해서 주문이 정상처리 되었을때 메일과 팩스로 전송을 하도록 처리하는 것입니다. 여기에서 ArrayList의 처리를 위해서
 using System.Collections;을 추가하였습니다. 그럼 이제 메인에서 처리되는 모습을 보겠습니다.

    1 OrderManager om = new OrderManager();

    2 MailManager mm = new MailManager();

    3 FaxManager fm = new FaxManager();

    4 

    5 om.OrderProcess = (OrderProcessed)MulticastDelegate.Combine(om.OrderProcess, new OrderProcessed(mm.SendMail));

    6 om.OrderProcess = (OrderProcessed)MulticastDelegate.Combine(om.OrderProcess, new OrderProcessed(fm.SendFax));

    7 

    8 om.ProcessOrder();

5, 6번째 줄이 델레게이트에 메소드들을 추가하는 부분입니다. 위에서 본것과는 조금 다른 모습인데요. 기본적인 델레게이트 선언 모습이라고 보시면 됩니다. MulticastDelegate.Combine으로 메소드들을 델레게이트와 연결시키는 것입니다. 이것을 좀더 쉽게 표현 한다면 두가지로 나누어서 볼수 있습니다.

    1 OrderManager om = new OrderManager();

    2 MailManager mm = new MailManager();

    3 FaxManager fm = new FaxManager();

    4 

    5 om.OrderProcess += new OrderProcessed(mm.SendMail);

    6 om.OrderProcess += new OrderProcessed(fm.SendFax);

    7 

    8 om.ProcessOrder();

위와 같이 += new 델레게이트이름 을 이용해서 선언 해주는 방법과

    1 OrderManager om = new OrderManager();

    2 MailManager mm = new MailManager();

    3 FaxManager fm = new FaxManager();

    4 

    5 om.OrderProcess += mm.SendMail;

    6 om.OrderProcess += fm.SendFax;

    7 

    8 om.ProcessOrder();

위와 같이 메소드 이름만으로만 선언 해줄수도 있습니다. 기억에 마지막 방법은 2.0인가 3.0이상부터 사용할수 있었던걸로 기억하고 있습니다. 뭐...암튼 3가지 방법중 편한 방법으로 델리게이트 선언를 해주면 될것입니다. 결과를 봐보면..

다음과 같이 주문내역이 고객의 메일과 팩스로 보내졌다는 내용이 출력되는 것을 볼수 있습니다. 만약 실제로 메일보내는 프로그램과 팩스 프로그램으로 설정되어있다면 주문 처리가 될때 같이 보내진다는 것입니다. 참 편하죠잉~

델리게이트에 대해서 좀 알아보았는데요. 저는 델리게이트, 이벤트, 쓰레드 이부분이 델리게이트 하나로 인해서 엄청 해깔리더군요. 아무래도 저의 실력탓이겠지만요 ㅠ.ㅠ

여러분들은 어떻게 이해가 되시는지요??
제가 참고했던 부분과 도움이 될만한 싸이트를 남기고 델리게이트에 대해서는 마무리 하도록 하겠습니다.

출처 및 도움 받은 곳 : 훈스 닷넷
훈스 닷넷 델리게이트 강의 : http://www.hoons.kr/Lecture/LectureView.aspx?BoardIdx=61&kind=4

728x90
반응형

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

C# 소수(Prime Number) 찾기  (0) 2010.10.12
C# 프로세스 목록 알아오기  (1) 2010.10.11
Thread 란?  (0) 2010.10.10
Windows Forms의 시작  (2) 2010.01.19
C# Event  (0) 2010.01.18
FileAndDirectory  (0) 2010.01.12
C# File Input/Output  (1) 2009.12.24
C# Collection  (0) 2009.12.21
Interface  (0) 2009.12.18
Class(5)  (0) 2009.12.18