2015년 3월 9일 월요일

뇌자극 C# 5.0 - 13강

-델리게이트와 이벤트-

13.1 델리게이트란?


비서처럼 어떤 일을 해줄 코드를 두고,
이 코드가 실행할 세부 코드는 컴파일 시점이 아닌
실행 시점에 부여하는 것을 콜백이라고 부르는데

델리게이트는 이 콜백을 구현하기 위해 사용된다.
델리게이트는 메소드에 대한 참조다.

한정자 delegate 반환형식 델리게이트이름 ( 매개변수목록 );

델리게이트는 인스턴스가 아닌 형식이다.

델리게이트를 이용하여 콜백을 구현하는 과정

1)델리게이트를 선언한다
2)델리게이트의 인스턴스를 생성한다. 인스턴스를 생성할 때는 델리게이트가 참조할 메소드를 매개 변수로 넘긴다.
3)델리게이트를 호출한다.

13.2 델리게이트는 왜, 그리고 언제 사용하나요?

프로그래밍을 하다 보면 "값"이 아닌 "코드" 자체를 매개 변수로 넘기고 싶을 때
델리게이트를 쓴다.

자세히 알아보자.

1)델리게이트를 선언한다.

delegate int Compare(int a, int b);

2) Comparer 델리게이트가 참조할 비교 메소드를 작성한다.

static int AscendComparer(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 - (i+1); i++)
   {
      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(AscendComparer); //array는 {2,3,4,7,10}

13.3 일반화 델리게이트

델리게이트는 보통의 메소드뿐 아니라 일반화 메소드도 참조할 수 있다.
이 경우에는 델리게이트도 일반화 메소드를 참조할 수 있도록 
형식 매개 변수를 이용하여 선언해야 한다.

delegate int Compare<T>(T a, T b);

예) 위의 함수를 일반화로 바꾼다면...

static void BubbleSort<T>(T[] DataSet, Compare<T> Comparer)
{
   int i = 0;
   int j = 0;
   int temp = 0;

   for(i = 0; i<DataSet.Length - (i+1); i++)
   {
      if(Comparer(DataSet[j], DataSet[j+1])>0
      {
         temp = DataSet[j+1];
         DataSet[j+1] = DataSet[j];
         DataSet[j] = temp;
      }
   }
}

13.4 델리게이트 체인

델리게이트 하나가 여러개의 메소드를 동시에 참조할 수 있다.

예제)

delegate void ThereIsAFire(string location);

void Call119(string location)
{
   Console.WriteLine("소방서죠? 불났어요! 주소는 {0}", location);
}

void ShotOut(string location)
{
   Console.WriteLine("피하세요!! {0}에 불이 났어요!", location);
}

void Escape(string location)
{
   Console.WriteLine("{0}에서 나갑시다!", location);
}


이렇게 선언한 메소드들은 델리게이트의 인스턴스가 자신들을 동시에 참조할 수 있도록 
+= 연산자를 이용하여 결합할 수 있다.

ThereIsAFire Fire = new ThereIsAFirs(Call119);
Fire += new ThereIsAFire(ShotOut);
Fire += new ThereIsAFire(Escape);

Fire("우리집");

-출력결과-
소방서죠?불났어요!주소는 우리집
피하세요! 우리집에 불이 났어요!
우리집에서 나갑시다!

13.5 익명 메소드

익명 메소드는 이름 그대로 이름이 없는 메소드다.
이름이 없는 메소드를 델리게이트에서 사용하는 법을 알아본다

delegate int Calculate(int a, int b);

라는 델리게이트가 있다면 익명 메소드로는 아래와 같이 쓴다.

public static void Main()
{
   Calculate Calc;
   calc = delegate(int a, int b)
           {
               return a + b;
           }
   Console.WriteLine("3+4 : {0}", Calc(3,4) );
}

익명 메소드는 delegate 키워드를 이용하여 선언한다.

델리게이트 인스턴스 = delegate (매개변수목록)
                          {
                             //실행하고자 하는 코드....
                          }

13.6 이벤트 : 객체에 일어난 사건 알리기

이벤트를 선언하고 사용하는 절차

1)델리게이트를 선언

delegate void EventHandler(string message);

2)클래스 내에 1)에서 선언한 델리게이트 인스턴스를 event 한정자로 수식해서 선언 한다

class MyNotifier
{
   public event EventHandler SomethingHappened;
   public void DoSomething(int number)
   {
      int temp = number % 10;
      if(temp != 0 && temp % 3== 0)
      {
          SomethingHappened(String.Format("{0}: 짝", number);
      }
   }
}

3)이벤트 핸들러 작성. 이벤트 핸들러는 1)에서 선언한 델리게이트와 일치하는 메소드면 된다.

class MainApp
{
    static public void MyHandler(string message)
    {
       Console.WriteLine(message);
    }
    //....
}

4)클래스의 인스턴스를 생성하고, 이 객체의 이벤트에 3)에서 작성한 이벤트 핸들러를 등록

class MainApp
{
   static public void MyHandler(string message)
   {
      Console.WriteLine(message);
   }
   static void Main(string[] args)
   {
     MyNotifer notifier = new MyNotifier();
     notifier.SomethingHappened += new EventHandler(MyHandler);
     for(int i = 1; i < 30; i++)
     {
         notifier.DoSomething(i);
     }
   }
}

5)이벤트가 발생하면 이벤트 핸들러가 호출된다.

class MainApp
{
   static public void MyHandler(string message)
   {
      Console.WriteLine(message);
   }
   static void Main(string[] args)
   {
     MyNotifer notifier = new MyNotifier();
     notifier.SomethingHappened += new EventHandler(MyHandler);
     for(int i = 1; i < 30; i++)
     {
         notifier.DoSomething(i);
     }
   }
}

13.7 델리게이트와 이벤트

이벤트는 델리게이트에 event 키워드로 수식해서 선언한 것에 불과하다.
이벤트가 델리게이트와 가장 크게 다른 점은 
이벤트는 외부에서 직접 사용할 수 없다는 것이다.
이벤트는 public 로 선언되어 있어도 
자신이 선언되어 있는 클래스 외부에서는 호출이 불가능 하다

델리게이트는 콜백 용도로 사용하고,
이벤트는 객체의 상태 변화사건의 발생을 알리는 용도로 구분해서 사용해야 한다.

댓글 없음:

댓글 쓰기