본문 바로가기

프로그램/유니티 C# 강좌

[유니티 C# 강좌] 17. 이벤트(Event), 대리자 (델리게이트, Delegate)

728x90
반응형

1. 이벤트(Event)

이벤트는 개체에서 작업 실행을 알리기 위해 보내는 메시지입니다. 

이벤트는 외부 이벤트 가입자(Subscriber)에게 특정한 일을 알려 줍니다.

이벤트는 event라는 키워드를 사용하여 클래스 내에서 필드처럼 정의됩니다.

 

이벤트에 가입하는 외부 가입자는 이벤트가 발생 할 때 어떤 명령들을 실행할지를 지정해 주는데 이를 이벤트 핸들러(Event Handler)라고 합니다.

 

이벤트는 += 연사자를 사용하여 이벤트 핸들러를 이벤트에 추가하면 -= 연산자를 사용하여 이벤트 핸들러에서 이벤트를 삭제합니다.

하나의 이벤트에는 여러 개의 이벤트 핸들러를 추가 할 수 있습니다.

이벤트가 발생되면 추가된 이벤트 핸들러들을 모두 순차적으로 호출합니다.

 

네임스페이스

using System;

 

사용 방법 : 이벤트

① using System; // using 지시문
...
② public event EventHandler 이벤트-이름 // 이벤트 정의
...
③ 클래스-이름.이벤트-이름 += new 이벤트-핸들러(실행-메서드-이름// 이벤트 연결
...
④ 실행 메서드 // 이벤트 발생

 

using UnityEngine; 
using System; // ① using 지시문 

class ButtonEvent 
{ 
    public event EventHandler Click; // ② 이벤트 정의 

    public void MouseButtonDown() 
    { 
        if (this.Click != null) 
        { 
            Click(this, EventArgs.Empty); // 이벤트 핸들러들을 호출 
        } 
    } 
} 

public class EventExample : MonoBehaviour 
{ 
    void Start() 
    { 
        ButtonEvent buttonEvent = new ButtonEvent(); 
        buttonEvent.Click += new EventHandler(ButtonClick);  // ③ 이벤트 연결    

        buttonEvent.MouseButtonDown(); // 출력 : 버튼 클릭 
        buttonEvent.MouseButtonDown(); // 출력 : 버튼 클릭 
        buttonEvent.MouseButtonDown(); // 출력 : 버튼 클릭 
    } 

    void ButtonClick(object sender, EventArgs e)  // ④ 실행 메서드 : 이벤트 발생 
    { 
        Debug.Log("버튼 클릭"); 
    } 
}

 

이벤트는 add, remvoe를 문맥키워드를 사용하여 접근을 제어합니다.

 

예제 : 문맥키워드 add, remove
private EventHandler class EvnetClass 
{ 
    private EventHandler myEventHandler; 

    public event EventHandler MyEventHandler 
    { 
        add { myEventHandler += new EventHandler(value); } 
        remove { myEventHandler -= new EventHandler(value); } 
    } 
}

 

2. 대리자(델리케이트, Delegate)

대리자를 사용하여 콜백 메서드를 정의할 수 있습니다.
대리자는 메소드를 대신해서 호출하는 역할을 합니다.
대리자를 통해 메서드를 매개변수로 전달할 수 있습니다. 

 

2.1 대리자 사용 방법

 

사용 방법 :  delegate

① 접근-제한자 delegate데이터-형식 델리케이트-이름(매개-변수);
...
②-1 델리케이트-이름변수-이름 = new 델리케이트-이름(콜백-메서드-이름);
/*또는*/②-2 델리케이트-이름 변수-이름 = 콜백-메서드-이름; // C# 2.0부터 사용가능
...
③ 메서드(..., 콜백-메서드-이름) // 메소드 콜
...
④ 메서드(...델리케이트-이름 콜백-메소드-이름) // 메소드 정의
⑤ 콜백-메서드-1
⑤ 콜백-메서드-2
...

 

2.2 대리자 사용 예제

 

using UnityEngine; 

public class DelegateExample : MonoBehaviour 
{ 

    delegate int CalculateDelegate(int a, int b); // ① 접근-제한자 delegate데이터-형식 델리케이트-이름(매개-변수); 

    void Start() 
    { 
        CalculateDelegate Plus = new CalculateDelegate(Add); // ②-1 델리케이트-이름변수-이름 = new 델리케이트-이름(콜백-메서드-이름); 
        CalculateDelegate Minus = Subtract; // ②-2 델리케이트-이름 변수-이름 = 콜백-메서드-이름; 

        DebugLog(1, 2, Plus); // 출력 : 3 ③ 메서드 (..., 콜백-메서드-이름) // 메소드 콜 
        DebugLog(4, 3, Minus); // 출력 : 1 ③ 메서드 (..., 콜백-메서드-이름) // 메소드 콜 
    } 
        
    void DebugLog(int a, int b, CalculateDelegate calculateDelegate) // ④ 메서드 (...델리케이트-이름 콜백-메소드-이름) // 메소드 정의 
    { 
        Debug.Log(calculateDelegate(a, b)); 
    } 
        
    int Add(int a, int b) // ⑤ 콜백-메서드-1 
    { 
        return a + b; 
    } 
        
    int Subtract(int a, int b) // ⑤ 콜백-메서드-2 
    { 
        return a - b; 
    } 
}

 

3. 제네릭 대리자(제네릭 델리케이트, General Delegate)

대리자도 제네릭 <T>를 이용하여 어떤 타입으로 일반화한 메서드를 만들 수 있습니다.

 

사용방법 : 제네릭 대리자

접근-제한자 T delegate 델리케이트-이름<T> (T 매개변수-이름 ...);

 

using UnityEngine; 

public class DelegateExample : MonoBehaviour 
{ 
    delegate T CalculateDelegate<T>(T a, T b); 

    void Start() 
    { 
        CalculateDelegate<int> Plus = new CalculateDelegate<int>(Add); 
        CalculateDelegate<float> Minus = new CalculateDelegate<float>(Subtract); 

        DebugLog(1, 2, Plus); // 출력 : 3  
        DebugLog(4.1f, 3.2f, Minus); // 출력 : 0.9  
    } 

    void DebugLog<T>(T a, T b, CalculateDelegate<T> calculateDelegate) 
    { 
        Debug.Log(calculateDelegate(a, b)); 
    } 

    int Add(int a, int b) 
    { 
        return a + b; 
    } 

    float Subtract(float a, float b) 
    { 
        return a - b; 
    } 
}

 

4. 대리자 체인(Delegate Chain)

대리자 체인을 이용하면, 대리자 인스턴스를 호출 할 수도 있습니다.

인스턴스를 추가 할 때는 += 연산자를, 삭제 할 때는 -= 연산자를 사용됩니다.

 

using UnityEngine; 

public class DelegateChainExample : MonoBehaviour 
{ 
    delegate void CalculateDelegate(int a, int b); 

    void Start() 
    { 
        CalculateDelegate calculateDelegate = Add; 

        calculateDelegate += Subtract; 
        calculateDelegate(3, 2); // 출력 : 5  
                                 //       1       
    } 

    void Add(int a, int b) 
    { 
        Debug.Log(a + b); 
    } 

    void Subtract(int a, int b) 
    { 
        Debug.Log(a - b); 
    } 
}

 

5. 대리자(Delegate), 이벤트(Event)

모든 이벤트는 특수한 대리자입니다.

대리자로 이벤트를 발생할 수도 있습니다.

 

using UnityEngine; 

class DelegateEventClass 
{ 
    public delegate void DelegateMethod(string message); 
    public event DelegateMethod EventMethod; 

    public void MultipleOf5(int number) 
    { 
        if (number % 5 == 0 && number != 0) 
        { 
            EventMethod(string.Format($"{number}는 5의 배수")); 
        } 
    } 
} 

public class DelegateEventExample : MonoBehaviour 
{ 
    void Start() 
    { 
        DelegateEventClass delegateEventClass = new DelegateEventClass(); 
        delegateEventClass.EventMethod += DebugLog; 

        for (int i = 0; i < 30; i++) 
            delegateEventClass.MultipleOf5(i); 
    } 

    void DebugLog(string message) 
    { 
        Debug.Log(message); 
    } 
}
728x90
반응형