학습 일자 : 2023.04.10


델리게이트 (Delegate)

delegate = 대리자

특정 매개 변수 목록 및 반환 형식이 있는 함수에 대한 참조를 나타내는 형식 대리자 인스턴스를 통해 함수를 호출 할 수 있음 → 함수를 변수에 담을 수 있음.

<aside> 💡 델리게이터 기본 구조 delegate 반환형 델리게이트이름(매개변수1, 매개변수2, …);

</aside>

반환형과 매개변수가 일치하는 함수를 델리게이트 변수에 할당 가능

델리게이트 변수를 함수 호출 방법과 동일하게 ( ) 통해 호출

델리게이트도 함수의 일종이기 때문에 함수 안에서 정의할 수 없음.

[델리게이트 간단 사용 예제]

		//델리게이트 정의
		public delegate float DelegateMethod1(float param1, float param2);
		public delegate void DelegateMethod2(string message);
		public delegate int DelegateMethod3(int param1, int param2);

		//델리게이트 변수 생성
		public DelegateMethod1 delegate1;
		public DelegateMethod2 delegate2;
		public DelegateMethod3 delegate3;

		public float plus(float x, float y) { return x + y; }

		public float Minus(float x, float y) { return x - y; }

		public void Message(string message) { Console.WriteLine(message); }

		//델리게이트 사용
		public void Test1()
		{
			////델리게이트 인스턴스 생성 
			delegate1 = new DelegateMethod1(plus); //new해서 생성하는 건 잘 안 쓰긴 함
			delegate2 = Message; //이 방식을 더 많이 씀

			//결과가 동일함 
			Console.WriteLine(plus(11.75f, 51.239f));
			Console.WriteLine(delegate1(11.75f, 51.239f)); 

			delegate2("메시지11"); //델리게이트 간단하게 사용하는 방법임

			delegate1.Invoke(20, 10); //델리게이트 정석 방법 : invoke를 통해 호출해야 함.
			delegate2.Invoke("메시지22");

			//delegate3 = Minus; 
			//오류 : 델리게이트에 함수 넣을 때는 반환형과 매개변수가 일치하는 함수만 넣을 수 있음

			//delegate float DelegateMethod4(float param1, float param2);
			//오류 : 델리게이트도 함수의 일종이기 때문에 함수 안에서 생성 할 수 없음

			Console.WriteLine(Minus(11.75f, 51.239f));
		}

델리게이트 체인 (Delegate Chain)

하나의 델리게이트 변수에 여러 개의 함수를 할당하는 것이 가능

델리게이트 체인 사용 하는 이유

정해진 일련의 작업 프로세스가 있을 때, 각각의 작업을 델리게이트에 추가해두고, 델리게이트만 실행을 하면, 추가 프로세스가 생겼을 때, 새로운 기능을 런타임 시점에 추가 가능함 → 추가해두면, 다음 델리게이트 호출 시점부터 추가 된 기능 실행이 포함되어 실행 됨. (프로그램 동작 중 추가, 삭제가 가능하다는 것이 델리게이트 체인을 쓰는 이유라고 할 수 있음)

[델리게이트 체인 예제]

		public delegate void DelegateChain();

		public void Func1() { Console.WriteLine("FUNC1"); }
		public void Func2() { Console.WriteLine("FUNC2"); }
		public void Func3() { Console.WriteLine("FUNC3"); }

		public void Test2()
		{
			Console.WriteLine("델리게이트 체인 생성");
			DelegateChain delegateChain;
			delegateChain = Func1;
			delegateChain += Func2; // Func2를 추가 할당
			delegateChain += Func3; // Func2를 추가 할당
			delegateChain(); 
			//=> 추가 할당 후 델리게이트를 호출하면, 할당 순서대로 메소드가 호출 됨.

			Console.WriteLine("\\n할당 했던 기능 제거");
			delegateChain -= Func2;
			delegateChain();

			Console.WriteLine("\\n델리게이트에 할당되지 않은 함수 제거");
			delegateChain -= Func2; 
			delegateChain();
			//할당되지 않은 함수 제거하려고 해도 오류 나지 않음 -> 없으면 안 빼감 

			Console.WriteLine("\\n함수 중복 호출");
			delegateChain += Func1; //Func1가 두번 호출 됨
			delegateChain();

			Console.WriteLine("\\n중복된 함수 중 하나를 제거한다면");
			delegateChain -= Func1; 
			delegateChain(); 
			//중복된 함수 중 가장 마지막에 등록 된 Func1이 제거 됨 (LIFO)
			
			Console.WriteLine("\\n=연산자를 통해 델리게이트에 할당");
			delegateChain = Func3; 
			delegateChain();
			//=연산자는 덮어쓰기 개념임. 
			//    -> 기존에 할당 되었던 체인이 다 사라지고 =으로 할당한 Func3만 남음
		}

<aside> 💡 실행 결과

델리게이트 체인 생성 FUNC1 FUNC2 FUNC3

할당 했던 기능 제거 FUNC1 FUNC3

델리게이트에 할당되지 않은 함수 제거 FUNC1 FUNC3

함수 중복 호출 FUNC1 FUNC3 FUNC1

중복된 함수 중 하나를 제거한다면 FUNC1 FUNC3

=연산자를 통해 델리게이트에 할당 FUNC3

</aside>

대리자의 지정자로서 사용

지정자로 사용할 때 매우 유용함.

델리게이트를 미완성 상태의 함수를 구성하고, 매개변수에 함수 자체를 넘겨주면서 미완성이었던 함수를 완성 시킴. (→ 델리게이트 특성인 “변수에 함수를 담을 수 있다”를 이용한 형태)