[HCI] 9주차 대리자와 이벤트

정수현·2025년 5월 4일

C#

목록 보기
10/10

2025-05-04


구성

📍 대리자 (Delegate)

Delegate 생성

Delegate +/- Operator

📍 이벤트 (Event)

Events 동작 원리

Events 구성 요소

  1. 이벤트 핸들러 대리자 (Delegate)
  2. 이벤트를 발생시키는 객체 (Publisher)
  3. 이벤트에 응답하는 객체 (Subscriber)
  4. 이벤트 매개변수 (Event Argument)



대리자

📍 대리자 특징

  • 함수를 변수처럼 다뤄서, 변수명으로 함수를 실행할 수 있다.

  • 함수가 어딨는지 주소값을 저장한다.

  • 함수 매개변수, 반환값이 대리자 선언과 일치해야 사용할 수 있다.

  • 대리자에 여러 다른 함수들을 할당할 수 있다. (하지만 함수 모양은 같아야 한다.)

  • 대리자는 코드 작성 시가 아니라, 프로그램 돌아갈 때 메모리에 만들어진다.

  • 대리자를 통해 메서드를 매개변수로 전달할 수 있다.
    → 대리자를 통해 함수 자체를 값처럼 전달할 수 있다.

  • 대리자를 사용하여 콜백 메서드를 정의할 수 있다.
    → 작업 끝나고 자동으로 실행될 함수를 미리 지정할 수 있다.

  • 여러 대리자를 연결할 수 있다.
    → 하나의 대리자에 여러 함수를 연결할 수 있다.

  • 단일 이벤트에 대해 여러 메서드를 호출할 수 있다.
    → 이벤트 하나에 함수 여러 개 연결할 수 있다.

  • 람다 식은 인라인 코드 블럭을 작성하는 더욱 간단한 방법이다.
    Action act = () => Console.WriteLine("Hello")

쉽게 말해

  • 어떤 함수가 실행될지 나중에 결정하고 싶을 때
  • 함수를 변수처럼 전달하고 싶을 때 사용한다.
void Hello() => Console.WriteLine("안녕!");
void Bye() => Console.WriteLine("잘가!");

void Execute(MyDelegate d) => d(); // 대리자를 매개변수로 받아 실행

Execute(Hello);  // "안녕!"
Execute(Bye);    // "잘가!"
  • 대리자 = 함수 실행권을 가진 '전화번호'
  • 전화번호만 저장해두고, 나중에 그 번호롤 전화한다. ⇒ 함수 홓출
  • 전화번호부에 여러 개 저장해서 한 번에 여러 곳 전화 가능하다. (멀티캐스트)


📍 대리자 정의, 생성 및 사용

  • delegate 키워드를 사용하여 정의한다.
  • new 키워드를 통하여 생성한다.
  • 대리자 호출로 메서드를 간접 호출한다.
// 대리자 정의
public delegate void DelegateMethod(int x);
// 대리자가 지칭할 메서드 구현
publicstatic void CallbackMethod(int x) { Console.WriteLine(x); }
// 대리자 생성 및 ㅊ기화
DelegateMethod dm = new DelegateMethod(CallbackMethod);
// 대리자를 통한 메서드 간접 호출
dm(100); // →CallbackMethod(100)이 호출된다.

🍀 대리자 사용 예시 1

// 대리자 정의
public delegate void Del(string msg); 
public class DelegateTest
{
	// 대리자가 가리킬 함수
	public static void DelegateMethod(string msg)
    { System.Console.WriteLine(msg); }
    
    // '대리자'를 매개변수로 받는 함수
    public static void MethodWithCallback(int x int y, Del callback)
    { callback("The number is " + (x + y).ToString()); }
    
    public static void Main(string[] args)
    {
    	// 대리자 생성 (연결)
    	Del handler = DelegateMethod; 
        
        // DelegateMethod("Hello") 호출
        handler("Hello"); 
        
        // DelegateMethod("The number is " + ( 1 + 2));
        MethodWithCallback(1, 2, handler);
        var mc = new MethodClass();
        Del d1 = mc.Method1;
        Del d2 = mc.Method2;
        Del d3 = d1 + d2;
    }
}

🍀 대리자 사용 예시 2

public class Click
{
	public void MouseClick(string what)
    { System.Console.WriteLine("마우스의 {0} 버튼이 클릭됐습니다.", what); }
    
    public void KeyBoardClick(string what)
    { System.Console.WriteLine("키보드의 {0} 버튼이 클릭됐습니다.", what);
}

public class DelegateTest
{
	// 대리자 정의
	public delegate void OnClick(string what);
    
    public static void Main(string[] args)
    {
    	Click  c = new Click();
        // 대리자 생성 (연결)
        OnClick dm = new OnClick(c.MouseClick); 
        dm("왼쪽");
        dm = new OnClick(c.KeyBoardClick);
        dm("스페이스")
    }
}



📍 대리자 Operator

  1. Combine (+) : 대리자를 결합하는 연산자
  2. Remove (-) : 대리자를 제거하는 연산자
static void Main()
{
	NumClass c = new NumClass();
    
    // 대리자 Combine
    Handler h = new Handler(c.Plus) + new Handler(c.Minus)
    
    // 대리자 Remove
    h = h- new Handler(c.Minus);
}



이벤트

📍 이벤트 핸들러 대리자

  • 이벤트에 응답하는 메소드를 가리키는 대리자
    public delegate void EventNameEventHandler(Object sender, EventArgs e)

  • Object sender 이벤트 발생 객체

  • EventArgs e 이벤트 발생 시 넘겨줄 추가 정보



📍 이벤트 송신기 (Publisher)

  • 이벤트를 발생시키는 객체
  • 이벤트를 선언한 클래스에서만 이벤트 호출(발생)
  • 하위 클래스에서 재정의하거나 호출 가능하도록 virtual로 정의한다.
public class EventPub
{
	// ① 이벤트 선언
	public event MyEventHandler MyEvent;
    
    protected virtual void OnMyEvent(EventArgs e)
    {
    	// ② 이벤트 호출
    	if(MyEvent != null) MyEvent(this, e);
    }
}



📍 이벤트 수신기 (Subscriber)

  • 이벤트에 응답하는 ㅡ객체
  • 이벤트 처리 메서드를 이벤트 대리자에 연결한다. (등록)
class EventSub
{
	// 이벤트 핸들러
	virtual void MyEventH(Object sender, EventArgs e) { ... }
}

EventPub p = new EventPub(); // 이벤트 송신기 객체
EventSub s = new Eventsub(); // 이벤트 수신기 객체
p.MyEvent += new MyEventEventHandler(s.MyEventH); // 이벤트 핸들러 등록

p.OnMyEvent(args); // 이벤트 요청

0개의 댓글