특정 매개 변수 목록 및 반환 형식이 있는 함수에 대한 참조
대리자 인스턴스를 통해 함수를 호출 할 수 있음
<델리게이트 정의>
delegate 반환형(void,float 등) 델리게이트이름(매개변수들);
public delegate float DelegateMethod1(float left, float right); // 함수를 대신 실행시킬 뿐이라서 { } 내용은 필요 없음
public delegate void DelegateMethod2(string str);
internal class Program
{
public static float Plus(float left, float right) { return left + right; }
public static float Minus(float left, float right) { return left - right; }
public static float Multi(float left, float right) { return left * right; }
public static float Divide(float left, float right) { return left / right; }
public static void Message(string message) { Console.WriteLine("메세지로 {0}을 전송합니다.", message); }
static void Main(string[] args)
{
DelegateMethod1 delegate1 = Plus;
//DelegateMethod1 delegate1 = Message; // 불가능 delegate의 반환형이 float라서 string은 저장 불가능!!
DelegateMethod2 delegate2 = Message; // DelegateMethod2 는 void와 매개변수가 string을 받는거라서 가능.
// 원래는 이렇게 사용. Invoke 부르다
delegate1.Invoke(20f, 10f); // 보관한 함수를 부르는 기능 -> 30
delegate1(20f, 10f); // Invoke를 간략하고 직관적으로 사용하기 위한 문법 허용 -> 30
float result;
result = delegate1(20f,10f);
Console.WriteLine(result); // 30
// <델리게이트 사용>
// 반환형과 매개변수가 일치하는 함수를 델리게이트 변수에 할당
// 델리게이트 변수에 참조한 함수를 대리자를 통해 호출 가능
delegate1 = Plus;
Console.WriteLine(delegate1(20f, 10f)); // Plus(20f, 10f) = 30
delegate1 = Minus;
Console.WriteLine(delegate1(20f, 10f)); // Minus(20f, 10f) = 10
delegate1 = Multi;
Console.WriteLine(delegate1(20f, 10f)); // Multi(20f, 10f) = 200
delegate1 = Divide;
Console.WriteLine(delegate1(20f, 10f)); // Divide(20f, 10f) = 2
}
}
- 델리게이트를 이용하여 특정 조건에서 반응하는 함수를 구현
- 함수의 호출(Call)이 아닌 역으로 호출받을 때 반응을 참조하여 역호출(Callback)
public class File
{
public void Save()
{
Console.WriteLine("저장하기 합니다.");
}
public void Load()
{
Console.WriteLine("불러오기 합니다.");
}
}
public class Button
{
public delegate void ClickListener();
public ClickListener clickListener;
public void Click()
{
if (clickListener != null)
{
clickListener();
}
}
}
public class Player
{
public void Jump()
{
Console.WriteLine("플레이어가 점프합니다");
}
}
static void Main(string[] args)
{
File file = new File();
// 하나의 콜백함수로 여러 기능을 담아 특정 조건에 맞게 출력
Button saveButton = new Button();
saveButton.clickListener = file.Save; //save 기능을 콜백함수에 담는다
Button loadButton = new Button();
loadButton.clickListener = file.Load; //load 기능을 콜백함수에 담는다
saveButton.Click(); // 저장하기
loadButton.Click(); // 불러오기
Player player = new Player();
Button jumpbutton = new Button();
jumpbutton.clickListener = player.Jump;
jumpbutton.Click(); // 점프하기
}
델리게이트 변수에 여러게의 함수를 참조하는 방법
- 하나의 델리게이트 변수에 여러 개의 함수를 할당하는 것이 가능
- +=, -= 연산자를 통해 할당을 추가하고 제거할 수 있음
- = 연산자를 통해 할당할 경우 이전의 다른 함수들을 할당한 상황이 사라짐
static void Main(string[] args)
{
Action action;
action = Func1; // 델리게이트에 Func1 로 초기화
action += Func2; // 델리게이트에 Func2 추가 참조
action += Func3; // 델리게이트에 Func3 추가 참조
action += Func2; // 같은 Func 중복 참조도 가능
action(); // Func1 - Func2 - Func3 -Func2
Console.WriteLine();
action -= Func2; // 저장한 Func2 참조 제거도 가능
action(); // Func1 - Func2 - Func3
Console.WriteLine();
action = Func3; // 델리게이트에 = 을 통해서 대입하는 경우, 이전의 참조된 상황이 사라짐
action -= Func1; // 델리게이트에 참조되지 않은 함수를 제거하는 경우, 해당 작업이 무시됨
action(); // Func3
action = Func2; // 델리게이트에 참조된 상황이 없을경우 터진다.
action -= Func2;
//action(); // 꼭 있을때만 호출!!
if (action != null) // 델리게이트에서 참조를 제거할 경우 참조하고 있는 함수가 없는 경우를 조심!!
{
action();
}
}
public static void Func1() { Console.WriteLine("Func1"); }
public static void Func2() { Console.WriteLine("Func2"); }
public static void Func3() { Console.WriteLine("Func3"); }
개발과정에서 많이 사용되는 델리게이트의 경우 일반화된 델리게이트를 사용
<Func 델리게이트>
- 반환형 매개변수를 지정한 델리게이트
- Func<매개변수1, 매개변수2, ..., 반환형>
int Plus(int left, int right) { return left + right; }
int Minus(int left, int right) { return left - right; }
void Main1()
{
Func<int, int, int> func;
func = Plus;
func = Minus;
}
<Action 델리게이트>
- 반환형이 void 이며 매개변수를 지정한 델리게이트
- Action<매개변수1, 매개변수2, ...>
void Message(string message) { Console.WriteLine(message); }
void Main2()
{
Action<string> action;
action = Message;
}
<Predicate 델리게이트>
- 반환형이 bool, 매개변수가 하나인 델리게이트
bool IsSentence(string str) { return str.Contains(' '); }
void Main3()
{
Predicate<string> predicate;
predicate = IsSentence;
}