본문 바로가기

CS/C#

[ C# ] Callback, Delegate, Event

1. Callback

콜백(Callback)

= 함수를 다른 함수에 전달하여 나중에 호출되도록 하는 기법 ( 의뢰인 → 비서 → 사장 )

= 주로 비동기 처리에 사용

= 비서 역할을 Delegate가 수행 가능

2. Delegate

대리자(Delegate)

= 메서드를 참조하는 타입

= 메서드를 매개변수로 전달하거나 변수에 할당할 수 있게 해줌

// Delegate 선언
public delegate void EnemyAttackHandler(float damage);

public class Enemy
{
    public event EnemyAttackHandler OnAttack;

    // 전달받은 Callback 메서드 호출
    public void Attack(float damage)
    {
        OnAttack?.Invoke(damage);
    }
}

public class Player
{
    // 실제로 호출될 Callback 메서드
    public void HandleDamage(float damage)
    {
        Console.WriteLine("플레이어가 {0}의 데미지를 입었습니다.", damage);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Enemy enemy = new Enemy();
        Player player = new Player();

        enemy.OnAttack += player.HandleDamage;
        
        // 플레이어가 10의 데미지를 입었습니다.
        enemy.Attack(10.0f);
    }
}

3. Event

이벤트(Event)

= 특정 상황이 발생했을 때 이를 알리기 위한 신호

= 이벤트 발생 시 특정 코드를 실행할 수 있도록 시스템 설계

 

이벤트 핸들러(EventHandler)

= 이벤트에 반응하여 실행되는 메서드

 

시스템

= Delegate 기반

= 이벤트를 구독하고 발행시키는 방식(구독자 패턴)으로 동작

public class Button
{
    // 이벤트 선언
    public event EventHandler Clicked;

    // 버튼 클릭 시 이벤트 발생
    public void OnClick()
    {
        Console.WriteLine("Button clicked.");
        Clicked?.Invoke(this, EventArgs.Empty);
    }
}

public class Program
{
    public static void Main()
    {
        Button button = new Button();
        
        // 이벤트 핸들러 등록
        button.Clicked += Button_Clicked;

        // 버튼 클릭 시뮬레이션
        button.OnClick();
    }

    // 이벤트 핸들러 메서드
    private static void Button_Clicked(object sender, EventArgs e)
    {
        Console.WriteLine("Button was clicked! Handling event.");
    }
}

 

public class PlayerDamagedEventArgs : EventArgs
{
    public int Damage { get; set; }
}

public class Player
{
    public int HP { get; private set; } = 100;

    // 이벤트 핸들러 선언
    public event EventHandler<PlayerDamagedEventArgs> PlayerDamaged;

    // 이벤트 등록
    public void TakeDamage(int damage)
    {
        HP -= damage;

        PlayerDamagedEventArgs e = new PlayerDamagedEventArgs { Damage = damage };
        PlayerDamaged?.Invoke(this, e);
    }
}

public class DisplayAndSound
{
    // 이벤트 핸들러 등록
    public DisplayAndSound(Player player)
    {
        player.PlayerDamaged += DisplayStatus;
        player.PlayerDamaged += DisplayHitEffect;
        player.PlayerDamaged += PlayHitSound;
    }

    // 데미지 상태를 출력하는 메서드
    void DisplayStatus(object sender, PlayerDamagedEventArgs e)
    {
        Player player = sender as Player;
        Console.WriteLine($"Player took {e.Damage} damage!");
        Console.WriteLine($"Remaining HP: {player.HP}");
    }

    // 피격 이펙트를 표시하는 메서드
    void DisplayHitEffect(object sender, PlayerDamagedEventArgs e)
    {
        Console.WriteLine("Displaying hit effect...");
    }

    // 피격 사운드를 재생하는 메서드
    void PlayHitSound(object sender, PlayerDamagedEventArgs e)
    {
        Console.WriteLine("Playing hit sound...");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Player player = new Player();
        DisplayAndSound displayAndSound = new DisplayAndSound(player);

        // 이벤트 발생
        player.TakeDamage(20);
        Console.WriteLine($"Player HP: {player.HP}");
    }
}

'CS > C#' 카테고리의 다른 글

[ C# ] 상속, 인터페이스, 추상 클래스  (1) 2024.11.05
[ C# ] 값 형식, 참조 형식  (0) 2024.09.26
[ C# ] 객체지향 프로그래밍  (0) 2024.07.26
[ C# ] 객체와 한정자  (0) 2024.07.26