1. delegate란
delegate는 메서드 대리자입니다.
delegate로 메서드 대리자를 선언해주고 원하는 메서드를 참조시킬수 있습니다.
쉽게말하면 함수를 보관하는 통을 만들고(대리자선언) 그 통안에 함수를 넣고
나중에 통을 가져와서 함수를 실행시키는 방식입니다.
2, 예제
namespace DelegateTest
{
// 대리자를 만들어준다.
delegate void Del();
// 매개변수가 없고 반환형이 void형인 메서드만 참조 시킬 수 있다.
class Mng
{
public void Main()
{
// myDel이라는 대리자 객체 생성
Del myDel;
// Print라는 메서드를 참조해준다.
myDel = Print;
// 대리자를 이용한 메서드 호출
myDel();
// 메서드를 참조하는 형식은 여러가지를 지원합니다.
// myDel = new Del(Print);
// myDel = Print;
// myDel += Print;
}
public void Print()
{
Console.WriteLine("대리자를 통한 메서드 호출입니다.");
}
}
}
위의 예제에서는 반환값이 없고 매개변수가 없는 메서드를 참조시킬수있는 대리자 Del을 선언한 예제입니다.
delegate int Del(int a) 로 선언하면
매개변수가 int형 반환형이 int형인 메서드를 참조 시킬 수 있습니다.
2. chain
아래와 같은 방법으로 new 키워드를 사용 하는 경우도 있고
+= 를 이용해서 여러 메서드를 참조시킬수도 있습니다.(-=를 이용하여 뺄 수도 있습니다.)
(통안에 여러개의 메서드를 넣을 수 있습니다.)
namespace DelegateTest
{
delegate void Del();
class Mng
{
public void Main()
{
Del myDel = new Del(Print);
myDel += Print2;
myDel();
}
public void Print()
{
Console.WriteLine("대리자를 통한 메서드 호출입니다.");
}
public void Print2()
{
Console.WriteLine("하나더 참조할게요~");
}
}
}
이처럼 메서드대리자 delegate는 메서드를 대리 할 수 있습니다.
사실 이것만 보면 delegate를 왜 쓰는거지? 하고 감이 잘 안옵니다.
3. delegate의 유용한 사용법
사실 이 통안에는 유용한 기능이 몇가지 있습니다.
1. 함수의 매개변수를 delegate로 받아와서 결합도를 낮출수 있다.(C의 함수포인터와 비슷)
2. 이 통에있는걸 비동기로 실행시킬 수 있다.
https://frozenpond.tistory.com/26
3. 이 통을 Event와 결합시켜서 사용 할 수 있다.
Delegate가 Event와 결합하게되면 이벤트가 발생했을때 구독자들에게 이벤트 발생을 알릴 수 있습니다.(콜백메서드 호출)
표면적으로만 보면 이벤트는 델리게이트와 결합되었고 메서드를 구독시켰으니 하나의 메서드(구독자가 갖고있는)라고 볼 수 있습니다.
특이한 점은 이 이벤트를 호출시키면 객체를 생성하지않고
구독자들이 있는 클래스의 메서드(콜백메서드)를 호출 할 수 있습니다.
4. callback 예제
namespace Delegateex
{
class Program
{
static void Main(string[] args)
{
Teacher a = new Teacher();
a.Run();
}
}
}
namespace Delegateex
{
// 반환형이 없고 매개변수가 int형인 delegate를
// namespace단에 선언합니다.
public delegate void MyDel(int score);
class Teacher
{
public void Run()
{
// 학생 두명 생성
Student1 stu1 = new Student1();
Student2 stu2 = new Student2();
// 각각의 학생의 Event(Delegate)에 메서드를 구독시킨다.
stu1.Stu1Event += GetScore;
stu2.Stu2Event += GetScore;
stu1.Run();
stu2.Run();
}
private void GetScore(int score)
{
Console.WriteLine(string.Format("당신의 점수는 {0}점 입니다.",score));
}
}
}
namespace Delegateex
{
class Student1
{
// 네임스페이스 단에 선언된 Mydel을 이벤트형식으로 선언
public event MyDel Stu1Event;
public void Run()
{
// 콜백메서드 호출
Stu1Event(80);
}
}
}
namespace Delegateex
{
class Student2
{
// 네임스페이스 단에 선언된 Mydel을 이벤트형식으로 선언
public event MyDel Stu2Event;
public void Run()
{
// 콜백메서드 호출
Stu2Event(100);
}
}
}
네임스페이스단에서 delegate를 선언해주고
같은 네임스페이스에 속한 클래스에서 event와 delegate를 결합한 event를 선언하게 되면
Student1, Student2클래스 에서 Teacher의 메서드를 Teacher객체를 생성하지않고 사용할 수 있습니다.
GetScore을 콜백메서드라고 합니다.(피호출자가 호출자의 메서드를 실행시키는상황을 콜백이라고 하며 해당메서드를 콜백메서드라고 합니다.)
로직을 간단히 정리하면
1. 선생님클래스에서 학생클래스의 Event를 구독한다.(event delegate에 메서드를 참조시켜준다)
2. 선생님클래스에서 학생클래스의 Run메서드를 호출한다.
3. Run메서드 안에는 Event가 들어있어서 구독자(선생님)에게 이벤트발생을 알린다.(구독자클래스(선생님)의 메서드를 객체를 생성하지않고 호출이 가능하다 -> 콜백이라고 한다)
4. 선생님의 GetScore메서드가 호출된다.
마지막으로 3번에 첨언하자면
public void Run()
{
int score = 80;
// 이벤트 호출
if(Stu1Event != null)
{
if(score >70)
Stu1Event(score);
}
}
이런식으로 이벤트의 구독자가 있는지 확인하고(NullRefException방지) 어떠한 조건(70점 이상)에 맞을때 이벤트를 발생시켜 콜백을 하는 경우가 많습니다.
'c#' 카테고리의 다른 글
[c#] lock 사용법 및 예제 (0) | 2020.08.03 |
---|---|
[c#] 스레드(Thread)사용법 및 예제 (4) | 2020.07.30 |
[c#] Try Catch 사용법 및 예제 (0) | 2020.07.28 |
[c#] static과 singleton사용예제 (0) | 2020.07.07 |
[c#] string의 초기화방법(string.empty, "", null) 및 string의 특징 (2) | 2020.06.12 |
댓글