본문 바로가기
개발💻/C#

[C#] Delegate 2

by Sports Entrepreneur 2024. 6. 24.

 C# 이벤트와 델리게이트: Func과 Action

1. 개요

  • 이벤트(Event): 특정 동작이나 상태의 변화를 나타내는 것. 사용자 인터페이스, 시스템 알림 등에서 자주 사용.
  • 델리게이트(Delegate): 메서드 참조를 저장하고 호출할 수 있는 타입. 메서드 포인터와 유사한 기능을 제공.

2. 이벤트와 델리게이트의 차이

이벤트:

  • 주로 UI, 시스템 이벤트 등에서 사용.
  • event 키워드를 사용하여 선언.
  • 이벤트 핸들러는 델리게이트를 기반으로 하며, 이벤트는 해당 델리게이트를 통해 발생.
public class Alarm
{
    public event Action OnAlarm;

    public void TriggerAlarm()
    {
        OnAlarm?.Invoke();
    }
}

 

델리게이트:

  • 메서드를 캡슐화하여, 런타임에 메서드를 동적으로 호출.
  • 직접 인스턴스화하여 사용할 수 있음.
public delegate void Notify(string message);

public class Notifier
{
    public Notify notificationDelegate;

    public void Notify(string message)
    {
        notificationDelegate?.Invoke(message);
    }
}

 

3. 실무에서의 응용

이벤트 시스템 설계: UI 프레임워크에서 버튼 클릭, 마우스 움직임 등의 이벤트를 관리.

public class Button
{
    public event Action OnClick;

    public void Click()
    {
        OnClick?.Invoke();
    }
}

 

동적 메서드 호출: 플러그인 시스템이나 다양한 알고리즘을 실행할 때 사용.

public class Calculator
{
    // Func 델리게이트는 두 개의 int를 입력으로 받아 int를 반환하는 메서드를 참조할 수 있습니다.
    public Func<int, int, int> calculationDelegate;

    // Calculate 메서드는 델리게이트를 호출하여 계산을 수행합니다.
    public int Calculate(int a, int b)
    {
        if (calculationDelegate != null)
        {
            return calculationDelegate(a, b);
        }
        else
        {
            throw new InvalidOperationException("Calculation method not set.");
        }
    }
}
public class Program
{
    public static void Main()
    {
        Calculator calculator = new Calculator();

        // 덧셈 계산 방법을 델리게이트에 할당합니다.
        calculator.calculationDelegate = (a, b) => a + b;
        Console.WriteLine("Addition: " + calculator.Calculate(3, 4)); // 출력: 7

        // 뺄셈 계산 방법을 델리게이트에 할당합니다.
        calculator.calculationDelegate = (a, b) => a - b;
        Console.WriteLine("Subtraction: " + calculator.Calculate(10, 3)); // 출력: 7

        // 곱셈 계산 방법을 델리게이트에 할당합니다.
        calculator.calculationDelegate = (a, b) => a * b;
        Console.WriteLine("Multiplication: " + calculator.Calculate(5, 6)); // 출력: 30

        // 나눗셈 계산 방법을 델리게이트에 할당합니다.
        calculator.calculationDelegate = (a, b) => a / b;
        Console.WriteLine("Division: " + calculator.Calculate(20, 4)); // 출력: 5
    }
}

 

 

4. 일반적인 실수와 해결 방안

메모리 누수: 이벤트 핸들러를 등록하고 해제하지 않을 경우 발생.

  • 해결 방안: 이벤트 핸들러 등록과 해제를 철저히 관리.
button.OnClick += Button_Click;
button.OnClick -= Button_Click;

 

* 메모리 누수(Memory Leak)는 프로그램이 더 이상 필요하지 않은 메모리를 계속해서 점유하고 있어 메모리가 해제되지 않는 현상입니다. 이는 특히 장기 실행 애플리케이션에서 심각한 문제를 일으킬 수 있습니다.

 

델리게이트 호출 시 null 체크: 델리게이트 인스턴스가 null일 경우 예외 발생 가능.

  • 해결 방안: ?.Invoke 연산자를 사용하여 안전하게 호출.
notificationDelegate?.Invoke("Message");

 

* 에러 내용

 

5. 디자인 패턴

 

옵저버 패턴(Observer Pattern):

  • 객체의 상태 변화를 관찰하고, 상태 변화가 있을 때 자동으로 통지.
  • 델리게이트와 이벤트를 활용하여 구현.
public class Subject
{
    public event Action OnChange;

    private int _state;
    public int State
    {
        get => _state;
        set
        {
            _state = value;
            OnChange?.Invoke();
        }
    }
}

public class Observer
{
    public void Subscribe(Subject subject)
    {
        subject.OnChange += () => Console.WriteLine("State changed!");
    }
}

 

커맨드 패턴(Command Pattern):

  • 요청을 캡슐화하여 호출자와 수행자를 분리.
  • Func 또는 Action 델리게이트를 사용하여 구현.
public class Command
{
    private readonly Action _execute;

    public Command(Action execute)
    {
        _execute = execute;
    }

    public void Execute()
    {
        _execute();
    }
}

public class Invoker
{
    private Command _command;

    public void SetCommand(Command command)
    {
        _command = command;
    }

    public void ExecuteCommand()
    {
        _command?.Execute();
    }
}

 

전략 패턴(Strategy Pattern):

  • 행위를 캡슐화하여 교환 가능하게 만들기.
  • Func 델리게이트를 사용하여 구현.
public class Context
{
    private Func<int, int, int> _strategy;

    public void SetStrategy(Func<int, int, int> strategy)
    {
        _strategy = strategy;
    }

    public int ExecuteStrategy(int a, int b)
    {
        return _strategy(a, b);
    }
}

 

'개발💻 > C#' 카테고리의 다른 글

[C#] Coupling, Cohesion 1  (0) 2024.08.10
[C#] Observer Pattern 1  (0) 2024.07.13
[C#] Delegate 1  (0) 2024.06.08
[C#] Using 지시문  (2) 2022.08.24
[C#] Namespace  (0) 2022.08.23