내일배움캠프

내일 배움캠프 16일차 : Action , Func 키워드를 사용한 이벤트 사용

pracumj 2024. 10. 4. 18:56

오늘 공부한 내용📝

오늘은 C#에서 `event`와 함께 `Action``Func`를 활용하는 방법을 학습했다. `delegate` 대신 `Action``Func`를 사용하면 더 직관적이고 간결한 코드를 작성할 수 있다. 이들의 차이점과 사용 시점을 이해하기 위해 다양한 예제를 실습해보았다.


왜 Action과 Func를 사용할까?🤔

기존 delegate를 사용하면 메서드 서명을 따로 정의해야 하는 번거로움이 있다. 하지만 Action과 Func를 사용하면 코드를 더 간단하게 작성할 수 있으며, 직관적인 형태로 메서드 서명을 지정할 수 있다.

  • Action반환값이 없는 메서드 호출 시 사용된다.
  • Func반환값이 있는 메서드 호출 시 사용된다.

Action 사용 예시 

Action은 반환값이 없는 메서드를 대신할 수 있다. 이를 통해 이벤트를 구독하고 이벤트 핸들러에서 필요한 작업을 수행할 수 있다.

using System;

public class Player
{
    // Action을 사용하여 이벤트 선언
    public event Action<int> OnDamage;  // 정수형 파라미터를 받지만 반환값은 없음

    private int health;

    public Player(int initialHealth)
    {
        health = initialHealth;
    }

    public void TakeDamage(int damage)
    {
        health -= damage;
        Console.WriteLine($"플레이어가 {damage}만큼의 피해를 입었습니다.");
        
        // 이벤트 호출 (외부에서는 이 호출을 막을 수 있음)
        OnDamage?.Invoke(health);
    }
}

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

        // 이벤트 구독 - 현재 체력을 출력하는 메서드로 구독
        player.OnDamage += DisplayHealthChange;

        // 플레이어에게 데미지를 줘서 이벤트 발생
        player.TakeDamage(30);
        player.TakeDamage(50);
    }

    static void DisplayHealthChange(int currentHealth)
    {
        Console.WriteLine($"현재 체력: {currentHealth}");
    }
}

 

출력 결과:
플레이어가 30만큼의 피해를 입었습니다.
현재 체력: 70
플레이어가 50만큼의 피해를 입었습니다.
현재 체력: 20

위 예시에서는 Action<int>를 사용하여 OnDamage 이벤트를 선언했다. Action<int>는 정수형 인자를 받아 특정 작업을 수행하지만, 반환값은 없다. player.OnDamage += DisplayHealthChange; 구문을 통해 이벤트를 구독하고, 체력이 변할 때마다 DisplayHealthChange 메서드가 호출된다

 

Func 사용 예시 

Func는 반환값이 있는 메서드를 대체할 수 있다. 특히 이벤트 핸들러에서 입력값을 받아 로직을 수행하고 그 결과를 반환할 때 유용하다.

using System;

public class Player
{
    // Func을 사용하여 이벤트 선언
    public event Func<int, bool> OnHealthCheck;  // 정수형 입력을 받아 bool을 반환

    private int health;

    public Player(int initialHealth)
    {
        health = initialHealth;
    }

    public void Heal(int healAmount)
    {
        if (OnHealthCheck?.Invoke(healAmount) ?? true)  // 이벤트 핸들러의 결과를 체크
        {
            health += healAmount;
            Console.WriteLine($"플레이어가 {healAmount}만큼 체력을 회복했습니다. 현재 체력: {health}");
        }
        else
        {
            Console.WriteLine("체력 회복이 실패했습니다.");
        }
    }
}

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

        // 이벤트 구독 - 체력 회복이 가능한지 체크하는 메서드로 구독
        player.OnHealthCheck += HealthRecoveryCheck;

        // 플레이어에게 회복 시도
        player.Heal(20);  // 성공
        player.Heal(-10); // 실패 (음수 값은 잘못된 값)
    }

    static bool HealthRecoveryCheck(int healAmount)
    {
        // 체력 회복량이 양수인지 확인
        return healAmount > 0;
    }
}
출력 결과:
플레이어가 20만큼 체력을 회복했습니다. 현재 체력: 70
체력 회복이 실패했습니다.

위 예시에서는 Func<int, bool>를 사용하여 OnHealthCheck 이벤트를 선언했다. Func<int, bool>은 정수형 인자를 받아 bool 값을 반환한다. 이처럼 Func를 사용하면 이벤트 핸들러에서 입력값을 처리하고 결과를 반환받아 로직을 제어할 수 있다

 

 

Action과 Func의 차이점 

  1. Action은 반환값이 없는 메서드를 대신하며, 이벤트에서 결과를 반환할 필요가 없는 경우 사용합니다. 예를 들어, 단순히 알림만 필요한 경우 또는 로그를 출력하는 경우에 사용됩니다.
  2. Func는 반환값이 있는 메서드를 대신하며, 입력값을 받아 결과를 반환해야 하는 상황에서 유용합니다. 예를 들어, 계산식을 처리하거나 입력값을 기반으로 새로운 값을 생성해야 할 때 사용됩니다.
  3.  

Action과 Func 사용 시점

  • Action 사용 시점: 이벤트가 발생했을 때 단순히 알림만 필요하거나, 수행 결과가 필요 없는 경우 
  • Func 사용 시점: 이벤트 핸들러의 결과값을 기반으로 로직을 수행하거나, 입력값을 받아 연산 후 반환값을 사용하는 경우 
 

마무리😺

Action과 Func는 delegate를 간편하게 대체할 수 있으며, 메서드 서명을 따로 정의하지 않아도 되기 때문에 코드 작성이 간결해진다. 앞으로 다양한 상황에서 Action과 Func를 활용하여 이벤트 핸들러를 관리하고, 더 안전하고 구조화된 코드를 작성해봐야겠다