반응형
Delegate[대리자]란?
- 메서드의 대리자
- 메서드를 보다 효율적으로 사용하기 위하여 특정 메서드 자체를 캡슐화 할 수 있게 만들어주는 방법

using System;

namespace DelegateTest
{
delegate void pis1();
delegate void pis2(int x);
class Test1
{
public void x1()
{
Console.WriteLine("Test1");
}
public void x2(int y)
{
Console.WriteLine("Test2 " + y);
}
}

class Test2
{
[STAThread]
public static void Main(string[] args)
{
Test1 t1 = new Test1();
pis1 p1 = new pis1(t1.x1);
pis2 p2 = new pis2(t1.x2);
p1();
p2(100);
}
}
}

============출력결과================
Test1
Test2  100
====================================

이게 Delegate[대리자]이다. 솔직히 -.- 왜 쓰는지 모르겠다. 밑의 소스를 보면 알겠지만

using System;

namespace DelegateTest
{
class Test1
{
public void x1()
{
Console.WriteLine("Test1");
}
public void x2(int y)
{
Console.WriteLine("Test2 " + y);
}
}
class Test2
{
[STAThread]
public static void Main(string[] args)
{
Test1 = new Test1();
t1.p1();
t1.p2(100);
}
}
}

============출력결과================
Test1
Test2  100
====================================

이 소스랑 다른게 몬가? 출력결과는 똑같은데... --;;; 이제 공부해야지...자 찾아보자
소설같은 C#의 5장 Delegate를 보면...간단하게 설명되어 있다. 몬소린지 하나도 모르겠다. 정말..-_-;
나중에 더 자세히 설명해준다는데...것참....

그래서 "vs 2005로 배우는 C#게임프로그래밍" 책을 봐야겠다.
좀 더 자세하게 설명되어 있다.

Delegate[델리게이트, 대리자]
- 대리자라는 사람은 무엇인가의 일을 대신해주는 사람이란 뜻이다. 이와 같이 C#에서는 어떠한 기능을 대신 수행해주는 역할
- Delegate[델리게이트, 대리자]는 사용자 정의형으로 정의할 수 있다.
 사용자 정의형의 대표적인 예는 Class[클래스]이다.

사용자 정의 -- delegate string dele(string Str);     함수(메서드)형태로 정의함
                 -- Class Main{ }
                 -- Class A { }
                 -- Class B { }
위의 그림(?)을 보면 클래스와 같은 위치에서 선언된다. 맨 위의 소스를 보면 이해될 것이다.

delegate void pis1();
delegate void pis2(int x);
class Test1
{
....

보이지? 클래스보다 먼저 선언했다. 같은 위치라는 것... 그리고 함수 형태로 정의한다는 것..리턴형도 있고 말야..+_+ 인자값도 있고
Delegate[델리게이트, 대리자]의 대표적 기능은 메서드를 대신수행하는 역할이란 것이다.
C언어에서는 포인터함수라는 개념이 있다는데 난 C전혀! 모르므로 패스! (-.ㅜ...이러니 내가 미쳐)
예제가 있다. 그런데 위의 예제와 거의 비슷하다. 그래서 또 패스! 할려다가....나에게 좀 필요한 기초가 있어서 만들겠다.

using System;
using System.Collections.Generic;
using System.Text;
namespace DelegateTest
{
//델리게이트 선언
delegate void dele1();
delegate int dele2(int a, int b);
//계산 클래스
class MathClass
{
public void Intro()
{
Console.WriteLine("계산을 시작합니다.");
}
public int Sum(int a, int b)
{
return a+b;
}
}

//프로그램 시작점
class Program
{
static void Main(string[] args)
{
//Math(계산)클래스 선언 및 인스턴스화
MathClass MathClass = new MathClass(); //전에 적은 거 같은데 MathClass MathClass가 클래스 선언
                                                             //new MathClass()가 인스턴스화 시키는 거라고 생각하면 됨
//델리게이트 선언 및 인스턴스화(델리게이트와 클래스는 같은 위치에서 선언된다.)
dele1 Sum1 = new dele1(MathClass.Intro);
dele2 Sum2 = new dele2(MathClass.Sum);
Sum1();
Console.WriteLine("Result : {0}", Sum2(-10, 90));
}
}
}

============출력결과===============
계산을 시작합니다.
Result : 80
===================================

앞의 예제와 거의 비슷하다. -0- 

먼저 MathClass를 만들었다. 이 클래스는 두개의 메서드를 가지고 있다. 하나는 반환형과 매개변수 없는 Intro함수 
하나는 덧셈기능을 수행하여 리턴해주는 Sum함수
자  그럼 먼저 8-9줄에 선언된 Delegate[델리게이트,대리자]를 보면 MathClass가 가지고 있는 함수와 똑같은 형식을 갖춘 Delegate 
두개가 선언되어있다.
dele1은 반환값이나 매개변수가 존재하지 않고 dele2는 두개의 int형 매개변수를 가지고 있으며 int형 반환값을 가지고 있다.

32,33번째 줄을 보면 선언된 델리게이트를 인스턴스화 시켰다. 그리고 생성자에는 메서드가 참조된다.
만약 dele1 Sum1 = new dele1() 이렇게 선언하면 에러가 발생한다. 즉 델리게이트는 반드시 메서드를 참조 시켜야한다는 것!

그리고 만약 dele1에 MathClass.Sum과 같은 매개변수와 선언형식이 다른 메서드를 참조 시키려고 해도 에러가 난다.

한마디로 요약하자면 Delegate 는 연결될 메서드를 반드시 참조시켜야하고 매개변수와 선언형식도 같아야한다는 것이다!

이제까지 Delegate의 기본적인 면만 봤다. 이제 더 고난이도로 접근 -_-; 



Delegate의 연산
- Delegate는 Combine과 Remove라는 두개의 연산메서드를 지원한다. 이말은
 Delegate가 여러 메서드의 참조가 가능하다는 것이다.

Combine : 기존의 위임에 또 다른 위임을 추가합니다.[+] //말을 어렵게 했는데...그냥 추가한다고 보면된다.
Remove : 기존의 위임에 특정 위임을 제거합니다. [-]

using System;
using System.Collections.Generic;
using System.Text;
namespace DelegateTest
{
delegate void deleMath(int Vlue); //델리게이트 선언
class MathClass
{
public int Number;
public void Plus(int Value); //더하기
{
Number += Value; //Number = Number + Value 와 같은 뜻
}
public void Minus(int Value) //빼기
{
Number -= Value; //Number = Number - Value 와 같은 뜻
}
public void Multiply(int Value) //곱하기
{
Number *= Value; //Number = Number * Value 와 같은 뜻
}
}

class Program
{
static void Main(string[] args)
{
//Math 클래스 선언 및 인스턴스화
MatchClass MathClass = new MathClass();
//Delegate 선언 및 인스턴스화(덧셈)
deleMath Math = new deleMath(MathClass.Plus);
//위임 연산(뺄셈, 곱셈 추가)
Math += new deleMath(MathClass.Minus);
Math += new deleMath(MathClass.Multiply);
//결과
MathClass.Number = 10;
Math(10);
Console.WriteLine("Result : {0}", MathClass.Number);
//위임 연산 (뺄셈 제거)
Math -= new deleMath(MathClass.Minus);
//결과
MathClass.Number = 10;
Math(10);
Console.WriteLine("Result : {0}", MathClass.Number);
//위임 연산(곱셈 제거)
Math -= new deleMath(MathClass.Multiply);
//결과
MathClass.Number = 10;
Math(10);
Console.WriteLine("Result : {0}", MathClass.Number);
}
}
}

============출력결과=====================
Result : 100
Result : 200
Result : 20
=========================================

9줄에 정의된 MathClass 메서드들을 살펴보면 3개의 연산 메서드들이 존재한다. 이 메서드들은 매개변수로 받은 값을 Number라는 전역
변수와 연산을 하고 Number변수에 저장된다.

코드 34줄을 보면 Math 델리게이트는 선언과 동시에 Plus메서드를 기본으로 참조 시켰다. 그리고 37, 38줄을 보면 += 연산을 이용하여 추가로
메서드를 추가하고 있다. 이제 Math 델리게이트는 3개의 메서드가 참조된 것이다. 플러스, 마이너스, 곱셈 메서드....

41줄에서 10 이란 매개변수를 넣어 델리게이트를 실행하면 이 델리게이트는 Plus(10), Minus(10), Multiply(10) 이라는 세 개의 
메서드를 차례로 호출하는 것과 같은 의미다.
그래서 결국은 100 이 출력된다.
나머지는 뺄셈 메서드를 빼주면 되고, 나머지는 곱셈 메서드를 빼주면 계산결과가 나온다.


추가 - 내가 위에 클래스랑 같이 Delegate를 선언해야한다고 했는데 ... 꼭 그런건 아닌듯하다.
다음 소스를 보면...
using System;
using System.Text;
namespace DelegateTest
{
class AddFunc
{
static public void Add(int First, int Second)
{
int res = First + Second;
Console.WriteLine("{0}+{1}+{2}", First, Second, res);
Console.ReadLine();
}
}
class MathOp
{
public delegate void Opdelegate(int First, int Second);
public Opdelegate Op;
protected int _first, _second;
public MathOp(int First, int Second)
{
_first = First;
_second = Second;
}
public void Invoke()
{
if (Op != null)
Op(_first, _second);
}
}

class MathDelegateApp
{
static void Main(string[] args)
{
MathOp mo = new MathOp(42, 27);
mo.Op = new MathOp.Opdelegate(AddFunc.Add);
mo.Invoke();
}
}
}
반응형

+ Recent posts