게임 개발 시 콜백함수를 많이 사용하게 되는데, 이것의 근간이 되는 기본개념들을 정리해 놓으려고 한다.
#델리게이트
-
기본
- 델리게이트의 본질은 메서드를 다룰 수 있는 참조형 이다.
- 복수 또는 단일 메서드를 대신하여 호출하는 역할을 한다 -> 같은 형식이어야 한다.(매개변수나 리턴형)
- 외부에서 호출 가능.(private, protected메서드는 호출 불가)
-
델리게이트 형식
- [접근 한정자] delegate return형 델리게이트형명(메서드 매개변수);
- delegate int DelegateType(string Name); -> DelegateType자체가 타입명이 된다.
-
델리게이트 사용
DelegateType DelegateMethod = new DelegateType(Function);
(초기버전에는 new로 생성)- 요즘에는 DelegateType DelegateMethod = Function;으로 사용
-
예시
namespae ConsoleApplication1 { //델리게이트 선언 delegate void DelegateType(string str); class A { public void printf(string str) { Console.WriteLine(str); } } class Program { static void Main(string[] args) { A = Test = new A(); //첫번쨰 방식 델리게이트 등록 방법.(C# 1.0이상에서 사용 가능) DelegateType DelMethod1 = new DelegateType(Test.Print); DelMethod1("Hello World1"); //printf함수 호출 //두번째 방식 델리게이트 등록 방법.(C# 2.0이상에서 사용 가능) DelegateType DelMethod2 = Text.Print; DelMethod1("Hello World2"); //printf함수 호출 } } }
#멀티캐스트 델리게이트
-
멀티캐스트
- 데이터를 여러 사용자에게 동시에 보낸다.
-
델리게이트 조합
- 다수 또는 단일 메서드 호출
- +=, -= 호출할 메서드 포함 또는 제
예시
class A
{
public void PrintA(string str)
{
Console.WriteLine("PrintA");
}
public void PrintB(string str)
{
Console.WriteLine("PrintB");
}
}
class Program
{
static void Main(string[] args)
{
A = Test = new A();
//델리게이트 등록
DelegateType DelFunc = Text.PrintA;
//델리게이트 추가
DelFunc += Test.PriontB;
DelFunc(); //PrintA, PriontB 호출.
//델리게이트 삭제
DelFunc -= Test.PriontB;
DelFunc(); //PrintA만 호출.
}
}
#이벤트(event)
-
의미
- 사전, 특정 상황이 발생했을 떄 알리고자 하는 용도(호출을 의미 + 데이)
- 이벤트를 발생시키는 클래스를 게시자라 하고
- 이벤트를 받거나 처리하는 클래스를 구독자라 한다.
- 델리게이트를 기반으로 한다.(메서드 호출)
이벤트와 델리게이트의 차이점은 이벤트는 public으로 선언되어 있어도 외부에서 사용할 수 가 없다.
이벤트는 메서드 안에서만 사용가능!!
-
형식
- [접근 한정자] event 델맄게이트형 이벤트명 (델리게이트기반이므로 미리 형식이 잡혀 있다.)
-
예시
//델리게이트 형식 정의 delegate void DelegateType(string message); classA { //이벤트 핸들러 선언 public event DelegateType EventHandler; public void Func(string Message) { //메서드 안에서만 사용가능!! EventHandler(Message); } }
-
사용이유(?)(내 생각)
- 그냥 델리게이트와 차이점이 별로 없어 보인다. 하지만 정의된 클래스 메서드 안에서만 사용가능하므로. 델리게이트로 내부로만 쓸 콜백함수 만들 떄 private로 선언했다면 외부에서 등록가능하도록 추가,삭제 함수를 만들어야하는데… 이벤트 함수를 쓰면 public으로 선언해도 외부에서 호출 못하므로.(등록 삭제는 외부에서 가능.)
-
이벤트에 메서드 추가 및 삭제
- 객체.이벤트핸들러 += 객체.메서드1;
- 객체.이벤트핸들러 += 객체.메서드2;2
- 객체.이벤트핸들러 -= 객체.메서드1;
-
이벤트의 핵심
- 이벤트 핸들러에 객체의 메서드를 연결
- 이벤트 핸들러는 객체 메서드에서 호출
- 이벤트 핸들러를 포함하는 객체 안의 메서드를 통해 다른 객체 또는 같은 객체의 메서드를 호출하기 위한 방법(같은 데이터 전달)
델리게이트 | 이벤트 | |
---|---|---|
공통점 : | 객체의 메서드 호출 | 객체의 메서드 호출 |
차이점 : | 델리게이트로 호출 | 이벤트를 포함한 메서드에서 호출 |
델리게이트로 연결 | 이벤트 핸들러에 연결 |
출처 : https://www.youtube.com/watch?v=B-yaWp900sQ
#Action과 Func
람다 식을 위한 전용 델리게이트
로서, 델리게이트의 일일이 정의해야 한다는 불편함을 없애기 위해 마소에서 델리게이트의 형식을 제네릭의 도움으로 일반화해서 BCL에 Action과 Func로 포함시켰다.
public delegate void Action<T>(T obj);
//--> 반환값이 없는 델리게이트로서 T 형식 매개변수는 입력될 인자 1개의 타입을 지정
public delegate TResult Func<TResult>();
//--> 반환갑이 있는 델리게이트로서 TResult 형식 매개변수는 반환될 타입을 지정
Action과 Func의 차이는 반환값의 유무
에 있다.
또한, 마소에서는 이러한 Action과 Func의 인자를 16개까지 받을 수 있도록 미리 정의해놨다.
Action
- Action은 반환값과 인자값이 없는 함수 포인터 ( 델리게이트 )
- 반환 형식이 없음
-
어떤 결과를 반환하는것을 목적으로 하지 않으며, 일련의 작업 수행을 목적
Action<string> logOut = (txt) => { Console.WriteLin(DateTime.Now + ": " + txt); };
Fucn
- 반환값과 인자값이 있는 함수 포인터 ( 델리게이트 )
- 반환 형식이 있음
-
인자 값 넣는다면 Func<인자1, 인자2, …, 반환>형식
//처음 두 int, int 타입은 인자 두개에 대응되고, 마지막 int 타입은 반환값에 대응 Func<int, int, int> myFunc = (a, b) => a + b; Console.WriteLine("10 + 2 == " + myFunc(10, 2)); //출력 결과 : 10 + 2 == 12