본문 바로가기
C#

C# - 이벤트헨들러 ( EventHandler )

by Classic Master 2024. 5. 15.
728x90

이벤트핸들러 ( EventHandler )

개요

  • 이벤트 핸들러는 객체가 특정 이벤트가 발생했을 때 실행되는 메서드를 나타내는 개념입니다. 주로 GUI 프로그래밍에서 사용되며, 버튼 클릭, 키 입력 등의 사용자 동작에 대한 응답을 처리하는 데 사용됩니다.

정의

  • 이벤트 핸들러는 이벤트가 발생했을 때 실행될 메서드를 나타내는 대리자(Delegate)입니다. 이벤트 발생 시에 등록된 핸들러 메서드가 호출되어 해당 이벤트에 대한 작업을 수행합니다.

이벤트 핸들러를 사용하는 이유?

  • 이벤트 핸들러는 보통 플레이어의 입력을 감지하고, 해당 입력에 따라 캐릭터의 움직임이나 공격 등의 동작을 처리해야 합니다. 이를 위해 이벤트 핸들러를 사용하여 특정 입력이 발생했을 때 실행되는 메서드를 정의하고, 이를 통해 캐릭터의 상태를 변경하거나 게임 화면을 업데이트합니다.
  • 이벤트 핸들러를 이용하면 코드를 더 모듈화할 수 있습니다. 이벤트와 그에 대응하는 처리 로직을 각각의 클래스에 나누어 구현함으로써 코드의 가독성과 유지보수성을 높일 수 있습니다. 또한, 객체 간의 결합도를 낮추어 유연성을 향상시킵니다. 객체가 독립적으로 작동할 수 있도록 하여 확장성을 높이고, 새로운 이벤트를 추가하거나 기존의 이벤트를 수정할 때 코드의 수정이 용이해집니다.


표현 방식
C#에서 이벤트 핸들러는 다음과 같은 형식을 따릅니다.

public event EventHandler EventName;

event : 이벤트를 선언하는 키워드입니다.
EventHandler : 이벤트 핸들러를 위한 대리자 타입입니다.
EventName : 이벤트의 이름을 나타냅니다.

 

이벤트 핸들러는 보통 EventHandler 대리자를 사용하며, 해당 이벤트가 발생했을 때 실행될 메서드의 시그니처가 void EventHandler(object sender, EventArgs e)와 같아야 합니다.

반응형

EventHandler 사용시 add 및 remove에 관해서

  • event 키워드를 사용하여 선언된 이벤트는 add 및 remove 액세서를 사용하여 이벤트에 대한 이벤트 핸들러를 추가하거나 제거할 수 있습니다. 여기에 대해 좀 더 자세히 설명하겠습니다.
    이벤트 핸들러를 명시적으로 제거하지 않으면 메모리 누수가 발생할 수 있습니다. 이벤트 핸들러를 추가할 때 해당 이벤트에 대한 참조가 생성되며, 이 참조가 제거되지 않으면 해당 이벤트 핸들러는 가비지 컬렉터에 의해 회수되지 않습니다. remove 액세서를 사용하여 이벤트 핸들러를 명시적으로 제거함으로써 메모리 누수를 방지할 수 있습니다.

이벤트 핸들러 장점 및 단점

장점

느슨한 결합

  • 이벤트 핸들러를 사용하면 이벤트 발생자와 이벤트 수신자 간의 결합도를 낮출 수 있습니다. 이는 코드의 유지보수성과 확장성을 높이는 데 도움이 됩니다.

다중 핸들러 지원

  • 하나의 이벤트에 대해 여러 개의 핸들러를 등록할 수 있습니다. 따라서 다양한 객체나 모듈에서 동일한 이벤트에 대한 처리를 수행할 수 있습니다.

비동기 처리

  • 이벤트 핸들러를 사용하여 비동기적으로 이벤트를 처리할 수 있습니다. 이는 UI 응답성을 유지하고 긴 작업을 수행하는 동안 프로그램이 멈추는 것을 방지하는 데 도움이 됩니다.

 

단점

메모리 누수

  • 이벤트 핸들러가 제대로 해제되지 않으면 메모리 누수가 발생할 수 있습니다. 이는 이벤트 핸들러가 오래 유지되어야 하는 경우 주의해야 할 사항입니다.

디버깅 어려움

  • 이벤트 핸들러를 사용하면 이벤트가 어떤 핸들러에 의해 처리되는지 추적하기가 어려울 수 있습니다. 따라서 디버깅이 어려울 수 있습니다.

예시

 

public class Button
{
    public event EventHandler Click;

    public void OnClick()
    {
        Click?.Invoke(this, EventArgs.Empty);
    }
}

public class Program
{
    static void Main()
    {
        Button button = new Button();
        button.Click += Button_Click;

        button.OnClick(); // 이벤트 발생

        Console.ReadLine();
    }

    static void Button_Click(object sender, EventArgs e)
    {
        Console.WriteLine("Button clicked!");
    }
}

 

위 예시에서는 Button 클래스가 이벤트 핸들러를 가지고 있고, 해당 버튼을 클릭할 때마다 등록된 핸들러가 호출됩니다.

 

 

플레이어가 적을 처치했을 때 이벤트 처리

public class Enemy
{
    public event EventHandler EnemyKilled;

    public void Die()
    {
        OnEnemyKilled();
    }

    protected virtual void OnEnemyKilled()
    {
        EnemyKilled?.Invoke(this, EventArgs.Empty);
    }
}

public class GameManager
{
    public void Initialize()
    {
        Enemy enemy = new Enemy();
        enemy.EnemyKilled += Enemy_EnemyKilled;
    }

    private void Enemy_EnemyKilled(object sender, EventArgs e)
    {
        Console.WriteLine("Enemy killed! Player gets 100 points.");
        // 점수 증가 및 기타 처리 로직 추가
    }
}

class Program
{
    static void Main()
    {
        GameManager gameManager = new GameManager();
        gameManager.Initialize();

        // 게임 실행 및 플레이어의 동작에 따라 적을 처치하는 등의 상황이 발생할 때
        // Enemy.Die() 메서드가 호출되어 EnemyKilled 이벤트가 발생하고, 
        // 이벤트 핸들러인 Enemy_EnemyKilled 메서드가 실행됩니다.
    }
}

 

 

 

간단한 주식 시장 시뮬레이터를 구현하면서 add 및 remove 액세서를 사용하는 예시를 보여드리겠습니다.

 

// 주식 시장 시뮬레이터 클래스
public class StockMarketSimulator
{
    // 이벤트 정의: 주식 가격이 업데이트될 때 발생하는 이벤트
    public event EventHandler<StockUpdateEventArgs> StockPriceUpdated
    {
        // 이벤트 핸들러 추가
        add
        {
            Console.WriteLine("Adding stock price update handler");
            stockPriceUpdated += value;
        }

        // 이벤트 핸들러 제거
        remove
        {
            Console.WriteLine("Removing stock price update handler");
            stockPriceUpdated -= value;
        }
    }

    private event EventHandler<StockUpdateEventArgs> stockPriceUpdated;

    // 주식 가격 업데이트 메서드
    public void UpdateStockPrice(string symbol, decimal price)
    {
        // 주식 가격 업데이트 이벤트 발생
        OnStockPriceUpdated(new StockUpdateEventArgs(symbol, price));
    }

    // 주식 가격 업데이트 이벤트 발생 메서드
    protected virtual void OnStockPriceUpdated(StockUpdateEventArgs e)
    {
        stockPriceUpdated?.Invoke(this, e);
    }
}

// 주식 업데이트 이벤트 인자 클래스
public class StockUpdateEventArgs : EventArgs
{
    public string Symbol { get; }
    public decimal Price { get; }

    public StockUpdateEventArgs(string symbol, decimal price)
    {
        Symbol = symbol;
        Price = price;
    }
}

class Program
{
    static void Main()
    {
        // 주식 시장 시뮬레이터 객체 생성
        StockMarketSimulator simulator = new StockMarketSimulator();

        // 주식 가격 업데이트 핸들러 추가
        simulator.StockPriceUpdated += (sender, e) =>
        {
            Console.WriteLine($"Stock price updated for {e.Symbol}: ${e.Price}");
        };

        // 주식 가격 업데이트 메서드 호출
        simulator.UpdateStockPrice("AAPL", 150.50m);

        // 주식 가격 업데이트 핸들러 제거
        simulator.StockPriceUpdated -= (sender, e) =>
        {
            Console.WriteLine("Stock price update handler removed");
        };

        // 다시 주식 가격 업데이트 메서드 호출
        simulator.UpdateStockPrice("GOOG", 2700.25m);
    }
}

위의 예시에서는 StockMarketSimulator 클래스를 통해 주식 시장 시뮬레이션을 구현하고, 주식 가격 업데이트가 발생할 때 이를 이벤트로 알리는 기능을 구현하였습니다. add 및 remove 액세서를 사용하여 주식 가격 업데이트 이벤트에 동적으로 이벤트 핸들러를 추가하고 제거하는 것을 확인할 수 있습니다.

728x90
반응형