Q.delegate(델리게이트)가 뭐야?
A. 메서드(함수)에 대한 참조(주소값,포인터)를 캡슐화 하는 형식(타입)이다.
즉, 메서드를 가리키는 포인터(C,C++의 포인터 아님) , C++의 함수포인터라고 생각하면 쉽다.
Type-Safe(타입-안전)이며 , 객체 지향적으로 설계되있는것이 특징이다.
Q.delegate(델리게이트)를 왜 쓰는건데?
A.
1.유연성 : 메서드(함수)를 변수처럼 다룰 수 있다. 런타임 중 메서드를 선택 또는 변경 할수 있음
2.콜백 함수 : 비동기 작업이나 이벤트 처리 시 , 특정 시점에 실행할 메서드를 델리게이트로 전달 가능
3.함수형 프로그래밍 지원 : 람다 표현식과 함께 사용시 간결하고 효율적인 코드 작성 가능
Q.delegate(델리게이트)를 어떡해 쓰는데?
A.
예시 1)
public class Program
{
// 반환 타입이 void이고, 매개변수가 없는 델리게이트
public delegate void SimpleDelegate();
// 반환 타입이 int이고, 두 개의 int 매개변수를 받는 델리게이트
public delegate int OperationDelegate(int a, int b);
// 델리게이트 메서드
public static void SayHello()
{
Console.WriteLine("Hello!");
}
public static int Add(int x, int y)
{
return x + y;
}
public static void Main()
{
// SimpleDelegate 델리게이트 인스턴스 생성 및 메서드 할당
SimpleDelegate simpleDel = new SimpleDelegate(SayHello);
simpleDel(); // 출력: Hello!
// OperationDelegate 델리게이트 인스턴스 생성 및 메서드 할당
OperationDelegate opDel = new OperationDelegate(Add);
int result = opDel(5, 3);
Console.WriteLine(result); // 출력: 8
}
}
예시2)
//델리게이트 안에 여러개의 메서드를 추가 할 수 있다.
public class Program
{
public delegate void Notify(string message);
public static void MethodA(string msg)
{
Console.WriteLine($"MethodA: {msg}");
}
public static void MethodB(string msg)
{
Console.WriteLine($"MethodB: {msg}");
}
public static void Main()
{
Notify notifyDel = MethodA;
notifyDel += MethodB; // 델리게이트 체인에 MethodB 추가
//+= 연산자로 메서드를 추가할수 있다.
notifyDel("Hello Delegates!");
// 출력:
// MethodA: Hello Delegates!
// MethodB: Hello Delegates!
}
}
예시2) 의 사용은 += 연산자로 델리게이트 변수에 메서드를 추가하고 있으며,
주로 반환타입이 void인 델리게이트에서 사용된다.
반환값이 있는 경우 체인에 연결된 마지막 메서드 반환값만 반환됨
Q.delegate(델리게이트)와 event(이벤트)와 관계가 있다는 무슨관계야?
A. 이벤트는 델리게이트를 기반으로 구현 된 함수포인터라고 생각하면된다.
하지만 event를 선언한 클래스 내부에서만 저장한 메서드들을 동작 시킬수 있다.
public class Publisher
{
// 이벤트 선언
public event Action OnChange;
public void RaiseEvent()
{
//이벤트 변수를 선언한 클래스 내부에서 Invoke()로 동작시키는 모습
//변수 뒤에 ?는 해당 이벤트가 null 이면 동작을 막는 예외처리 키워드이다.
OnChange?.Invoke();
}
}
public class Subscriber
{
public void Subscribe(Publisher publisher)
{
//이벤트 변수에 메서드를 추가하고 있다.
//이벤트는 외부에서도 추가/삭제가 가능하다.
publisher.OnChange += Respond;
}
private void Respond()
{
Console.WriteLine("Event received and handled.");
}
}
public class Program
{
public static void Main()
{
Publisher publisher = new Publisher(); //이벤트 변수가 있는 클래스
Subscriber subscriber = new Subscriber(); //이벤트 변수에 메서드를 추가하는 클래스
subscriber.Subscribe(publisher);
publisher.RaiseEvent(); // 출력: Event received and handled.
}
}
subscriber 클래스를 보면 이벤트가 들어있는 변수(publisher)를 인자값으로 가져간 뒤 event에 메서드를 저장 한다.
그 이후 publisher에서 invoke()로 함수 동작시 subscriber의 함수가 동작하게 된다.
이렇게 외부 클래스의 함수를 특정 시점에 원할때 쓸 수있는것이 event 함수이다.
이 패턴은 옵저버 패턴과 매우 유사하다.
Q.C#에서 델리게이트 기반으로 된 함수포인터 변수는 event가 끝인거야?
A.물론 아니다.
보통 6개의 델리게이트를 많이 사용하게 될 것이다.
1. Delegate 기본 타입 : 모든 델리게이트의 기본 클래스.
2. Event 델리게이트 : 이벤트 처리에 사용되는 델리게이트.
3. Action 델리게이트 : 반환값이 없는 메서드를 참조.
Action action = () => Console.WriteLine("Hello");
action(); // 출력: Hello
Action<int> printNumber = (number) => Console.WriteLine(number);
printNumber(10); // 출력: 10
4. Func 델리게이트 : 반환값이 있는 메서드를 참조.
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 4)); // 출력: 7
5. Predicate 델리게이트 : bool 값을 반환하는 조건 검사를 위한 메서드 참조.
Predicate<int> isEven = (x) => x % 2 == 0;
Console.WriteLine(isEven(4)); // 출력: True
Console.WriteLine(isEven(3)); // 출력: False
이 델리게이트는 List 컨테이너의 Find 함수에 인자값으로 안내가 되어있다.
6. Comparison 델리게이트 : 두 객체를 비교하는 메서드 참조.
Comparison<int> comparison = (a, b) => a.CompareTo(b);
int[] numbers = { 3, 1, 4, 1, 5 };
Array.Sort(numbers, comparison);
주로 정렬에 사용된다.
오늘 TextRPG 팀프로젝트를 하고 발표를 하는 중 delegate를 사용한 팀이 있어서
생각해보니 정확한 개념을 모르는 것 같아 다시 한번 정리해 보았다.