델리게이트 (Delegate)

 델리게이트는 메소드에 대한 참조입니다. 즉, 델리게이트는 하나의 형식(type) 입니다.

델리게이트는 인스턴스 메소드, 정적메소드 모두 참조가능합니다.

프로그래밍을 할때 매개변수에 값을 넘겨 쓸모있는 메소드를 만들었습니다. 델리게이트는 값이 아닌 '코드' 자체를 넘기고 싶을때 사용할 수 있습니다.

사용방법은 다음과 같습니다.

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

 

어떤 데이터를 정렬하고자 할때  오름차순이나 내림차순, 중앙부터 가까운 순으로 정렬 등, 프로그래머가 원하는 정렬방식을 사용하도록 메소드만 건네주기만 하면 됩니다.

코드를 보겠습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CsharpStudy
{
    class Program
    {
        delegate int Compare(int number1, int number2);

        static int AscendCompare(int number1, int number2)
        {
            if (number1 > number2)
                return 1;
            else if (number1 == number2)
                return 0;
            else
                return -1;
        }

        static int DescendCompare(int number1, int number2)
        {
            if (number1 < number2)
                return 1;
            else if (number1 == number2)
                return 0;
            else
                return -1;
        }

        static void ExchangeData(ref int number1, ref int number2)
        {
            int Temporary=number1;
            number1 = number2;
            number2 = Temporary;
        }

        static void BubbleSort(int [] Data , Compare Comparer)
        {
            for (int j = 0; j < Data.Length; j++)
            {
                for (int i = 0; i < Data.Length - 1 - j; i++)
                {
                    if (Comparer(Data[i], Data[i + 1]) > 0)
                    {
                        ExchangeData(ref Data[i], ref Data[i + 1]);
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            int[] DataSet = new int[]{ 10, 5, 2, 9, 8, 1, 6, 3, 2, 5 };

            BubbleSort(DataSet, AscendCompare);
            Console.WriteLine("==Sorted by Ascend==");
            foreach(int num in DataSet)
            {
                Console.Write(" {0}", num);
            }
           
            Console.WriteLine(Environment.NewLine+"==Sorted by Descend==");
            BubbleSort(DataSet, DescendCompare);
            foreach (int num in DataSet)
            {
                Console.Write(" {0}", num);
            }
        }
    }
}

 

 

 

델리게이트 체인(Delegate Chain), 익명메소드 (Anonymous Method)

 델리게이트 하나가 여러개의 메소드를 동시에 참조할 수 있습니다. 체인처럼 델리게이트를 연달아 등록하여, 순서대로 참조된 함수들을 호출합니다.

델리게이트를 등록할때는 += 연산자 또는 Delegate.Combine() 메소드를 이용할 수 있고, 체인을 끊고 싶을 때는 -= 연산자 또는 Delegate.Remove() 메소드를 이용하면 됩니다.

 

익명메소드는 델리게이트가 참조할 메소드가 필요한데, 이 메소드가 다시 사용할 일이 없다고 판단될때 이름이 없는 메소드를 참조하면 됩니다.

익명 메소드는 다음과 같이 만들 수 있습니다.

delegate (매개변수_목록)

{

//실행코드

}

델리게이트 체인과, 익명 메소드 예제입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CsharpStudy
{
    class Program
    {
        delegate void DelegateChains();
  
        static void Print1()
        {
            Console.WriteLine("Welcome");
        }
        static void Print2()
        {
            Console.WriteLine("To");
        }
        static void Print3()
        {
            Console.WriteLine("C#");
        }

        static void Main(string[] args)
        {
            Console.WriteLine("==체인 연결==");
            DelegateChains chaincall = new DelegateChains(Print1);
            chaincall += Print2;
            chaincall += Print3;
            chaincall();

            Console.WriteLine("== 체인 끊기 ==");
            chaincall -= Print1;
            chaincall -= Print3;
            chaincall+=
                delegate()
                {
                    Console.WriteLine("Anonymous Method call");
                };
            chaincall();
        }
    }
}

 

 

이벤트(Event)

 프로그래밍을 할때 보통 순차적으로 진행되고는 했습니다. 하지만 어떤 일이 생겼을 때 이를 알려주는 객체가 필요할 때가 있습니다. 이 객체를 만들 때 사용하는 것이 이벤트(Event) 입니다.

이벤트는 어떤 일이 일어났을 때, 그 때 실행되는 코드입니다.

이벤트기반 프로그래밍(Event-driven programming)은 마우스를 움직이고, 클릭하고, 키보드를 입력하는 등 사용자가 명령하는 것에 대해서 프로그램이 그에 맞는 반응을 하는 것처럼 이벤트 기반으로 만들어진 프로그래밍 방식입니다.

 

이벤트는 델리게이트를 event 한정자로 수식해서 만듭니다. 그 과정은 다음과 같습니다.

1. 델리게이트를 선언합니다. (이 델리게이트는 클래스 안과 밖 아무곳에나 선언해도 됩니다.)

2. 클래스내에 1번에서 선언한 델리게이트의 인스턴스를 event 한정자로 수식하여 선언합니다.

3. 이벤트 핸들러를 작성합니다. 이벤트 핸들러는 1번에서 선언한 델리게이트와 일치하는 메소드여야 합니다.

4. 클래스의 인스턴스를 생성하고 이 객체의 이벤트에 3번에서 작성한 이벤트 핸들러를 등록합니다.

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

 

이벤트 예제입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CsharpStudy
{
    class Program
    {
        delegate void EventHandler(string message);

        class Notifier
        {
            public event EventHandler SomethingHappened;

            public void DoSomething(int number)
            {
                if (number == 5)   // 숫자가 5일때 이벤트가 발생한다고 생각합니다.
                {
                    SomethingHappened("이벤트 발생! (number 값:}" + number.ToString());
                }
            }
        }

        static void Main(string[] args)
        {
            Notifier notifier = new Notifier();
            notifier.SomethingHappened += MyHandler;  // 발생시킬 이벤트를 등록한다.

            for (int i = 0; i < 30; i++)  // 프로그램이 진행된다.  ( 대기상태에서 숫자 5일때 등록한 이벤트가 발생하게 된다. )
                notifier.DoSomething(i);
        }

        static void MyHandler(string message)
        {
            Console.WriteLine(message);
        }

    }
}

 

 

이벤트 처리기에 등록하지 않아도 컴파일 에러가 발생하지 않습니다. 따라서 이벤트를 만들었을 때 초기화를 하지 않으면, 이벤트가 발생해도 아무런 일이 일어나지 않은 것처럼 나오기 때문에 항상 초기화하는 습관을 갖는 것이 좋을 듯 합니다.

 

이벤트는 델리게이트에 event를 수식해서 선언한 것에 불과합니다. 하지만 이벤트가 델리게이트와 가장 큰 차이점은 이벤트는 외부에서 직접 사용할 수 없다는 데 있습니다. 이벤트는 public 한정자로 선언되어 있어도 자신이 선언되어 있는 클래스 외부에서는 호출이 불가능합니다. 이는 이벤트 기반 프로그래밍을 할 때 안정성을 추구할 수 있게 합니다.

예를 들어 네트워크 상태변화에 대한 사건을 알리는 클래스를 만들었다고 하면, 클래스 내부에서 객체를 감시하며 네트워크 상태를 체크하지만, 클래스 외부에서 네트워크 상태 변화 이벤트를 줄 수 있다면, 이미 네트워크 상태는 신뢰할 수 없게 됩니다.

 

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

 

 

 

이상으로 델리게이트와 이벤트에 대해서 정리해보았습니다.

 

 


<참고문헌>

뇌를 자극하는 C# 4.0 프로그래밍 - 박상현 저 

 
블로그 이미지

laboputer

소프트웨어를 전공하는 대학생

카테고리

전체보기 (24)
Programming with C# (15)
storage of informati.. (1)
Algorithm (1)
학교수업 (7)