Humility

아무리 노력해도 최고가 되지 못할 수 있다⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀그럼에도 노력하는자가 가장 겸손한 것 아닌가

공부하는 블로그

유니티/문법

[Unity] 유니티 C#) Delegate ( 델리게이트 ), Anonymous Method (익명 메서드) ,Lambda ( 람다 )

새벽_글쓴이 2025. 1. 7. 17:18
반응형

델리게이트란?

메소드를 참조하는 타입으로, 메소드를 변수처럼 저장하고 전달할 수 있게 해주는 기능


특징

  • 메소드를 참조할 수 있는 타입
  • 타입 안정성 보장
  • 체인(다중 델리게이트)이 가능
  • 메소드 시그니처가 일치해야 함

사용하는 이유

  • 콜백 메커니즘 구현
  • 이벤트 처리
  • 메소드를 매개변수로 전달
  • 유연한 코드 설계

활용 사례

  • 이벤트 시스템
  • 비동기 프로그래밍
  • 플러그인 아키텍처

예시 코드

public class PlayerSystem : MonoBehaviour
{
    // 델리게이트 정의
    public delegate void PlayerStatusChanged(int health, int mana);
    public event PlayerStatusChanged OnStatusChanged;

    private int health = 100;
    private int mana = 100;

    public void TakeDamage(int damage)
    {
        health -= damage;
        // 델리게이트 호출
        OnStatusChanged?.Invoke(health, mana);
    }

    // 델리게이트 활용 예시
    private void Start()
    {
        // UI 업데이트 메소드 등록
        OnStatusChanged += UpdateUI;
        // 사운드 재생 메소드 등록
        OnStatusChanged += PlaySound;
    }

    private void UpdateUI(int health, int mana)
    {
        Debug.Log($"UI Updated - Health: {health}, Mana: {mana}");
    }

    private void PlaySound(int health, int mana)
    {
        Debug.Log("Playing damage sound effect");
    }
}

익명 메서드란?

이름이 없는 메서드를 즉석에서 선언하고 사용할 수 있는 기능

delegate 키워드를 사용하여 정의함


사용 방법

// 익명 메서드의 기본 형태
delegate(매개변수) { 
    // 메서드 본문
}

// 예시
delegate void MyDelegate(string message);
MyDelegate myDelegate = delegate(string message) {
    Debug.Log(message);
};

예시

OriginMethod
delegate int delegateCalc(int a, int b);

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

void Start()
{
    delegateCalc cal = plus;
    cal(2, 4);
}

 

↓ ↓ ↓ ↓ ↓

AnonyMousMethod
delegate int delegateCalc(int a, int b);

void Start()
{
    delegateCalc cal = delegate (int i, int j)
    {
        return i + j;
    };   
    
    Debug.Log(cal(9,2));
}

특징

  • 이름이 불필요 ( 일회성으로 사용되는 메서드를 간단히 정의 )
  • 다른 메서드를 넣어주지 않고 델리게이트의 선언과 정의를 동시에 수행
  • 외부 변수 접근 가능 ( 클로저 )
private void CreateCounter()
{
    int count = 0;
    Button button = GetComponent<Button>();
    
    button.onClick.AddListener(delegate() {
        count++;  // 외부 변수 count에 접근 가능
        Debug.Log($"Count: {count}");
    });
}
  • 델리게이트와 함께 사용
public class GameManager : MonoBehaviour
{
    public delegate void ScoreChanged(int newScore);
    public event ScoreChanged OnScoreChanged;

    private int score = 0;

    private void Start()
    {
        // 익명 메서드로 이벤트 핸들러 등록
        OnScoreChanged += delegate(int newScore) {
            Debug.Log($"Score changed to: {newScore}");
            UpdateUI(newScore);
        };
    }

    private void UpdateUI(int score)
    {
        // UI 업데이트 로직
    }
}

사용하는 이유

  • 일회성 메서드를 간단히 구현
  • 코드의 간결성 향상
  • 지역 변수에 쉽게 접근 가능
  • 이벤트 핸들러를 즉석에서 정의

활용 사례와 예시 코드

이벤트 핸들링
public class UIManager : MonoBehaviour
{
    public Button startButton;
    public Button quitButton;
    
    private void SetupButtons()
    {
        // 시작 버튼 이벤트
        startButton.onClick.AddListener(delegate() {
            PlayerPrefs.SetInt("GameStarted", 1);
            SceneManager.LoadScene("GameScene");
        });

        // 종료 버튼 이벤트
        quitButton.onClick.AddListener(delegate() {
            SaveGameData();
            Application.Quit();
        });
    }

    private void SaveGameData()
    {
        // 게임 데이터 저장 로직
    }
}

 

일회성 이벤트 처리나 콜백 함수에서 매우 유용하게 사용된다

람다식 (Lambda Expression) 이란?

익명 메소드를 간단히 작성할 수 있게 해주는 표현식


사용 방법

=> (람다 연산자)를 사용하여 작성


예시

방법 1
// 기본적인 람다식
MyDelegate delegate2 = (message) => Debug.Log(message);

// 여러 줄의 람다식
MyDelegate delegate3 = (message) => {
    string upperMessage = message.ToUpper();
    Debug.Log(upperMessage);
};

// Action과 람다식
Action<string> action = (message) => Debug.Log(message);

// Func과 람다식 (반환값이 있는 경우)
Func<int, int> square = x => x * x;

 

방법 2

 

익명 메서드

void Start()
{
  delegateCalc cal = delegate (int i, int j)
    {
        return i + j;
    };
}

 

↓ ↓ ↓ ↓ ↓

 

람다식 방법 1 ( 매개변수 타입 생략 )

void Start()
{
	delegateCalc cal = (i, j) =>
      {
          return i + j;
      };
}

 

람다식 방법 2 (중괄호,return 키워드 추가 생략)

delegate int delegateCalc(int a, int b);
void Start()
{
	delegateCalc cal = (i, j) => i + j;

	Debug.Log(cal(9,2));
}

특징

  • 익명 메소드를 간단히 표현
  • => 연산자 사용
  • 컴파일러가 타입 추론
  • 클로저(외부 변수 캡처) 지원

사용하는 이유

  • 코드 간소화
  • 일회성 메소드 구현
  • LINQ 쿼리 작성
  • 즉시 실행 가능한 코드 블록 생성

활용 사례

  • LINQ 쿼리
  • 이벤트 핸들러
  • 컬렉션 조작
  • UI 이벤트 처리

예시 코드

public class ItemSystem : MonoBehaviour
{
    private List<Item> inventory = new List<Item>();

    public class Item
    {
        public string Name { get; set; }
        public int Level { get; set; }
        public float Price { get; set; }
    }

    private void ProcessItems()
    {
        // 람다식을 사용한 아이템 필터링
        var highLevelItems = inventory.Where(item => item.Level > 50);

        // 람다식을 사용한 아이템 정렬
        var sortedItems = inventory.OrderBy(item => item.Price);

        // 람다식을 사용한 아이템 변형
        var itemNames = inventory.Select(item => item.Name);

        // UI 버튼에 람다식 활용
        Button sellButton = GetComponent<Button>();
        sellButton.onClick.AddListener(() => {
            var selectedItem = inventory.FirstOrDefault(item => item.Level > 0);
            if (selectedItem != null)
            {
                SellItem(selectedItem);
            }
        });
    }

    private void SellItem(Item item)
    {
        Debug.Log($"Selling {item.Name} for {item.Price} gold");
    }
}

람다식과 익명메서드의 비교

익명 메서드
Button button = GetComponent<Button>();
button.onClick.AddListener(delegate() {
    Debug.Log("Button clicked!");
});

 

람다식
Button button = GetComponent<Button>();
button.onClick.AddListener(() => {
    Debug.Log("Button clicked!");
});

델리게이트와 람다식의 기능을 상황에 맞게 적절히 조합하여 사용하면
더 효율적이고 유지보수가 쉬운 코드를 작성할 수 있다.

또한, 람다식이 더 간결한 문법을 제공하기에 익명메서드 보단
람다식이 보다 선호하는 경향이 있다
그래도 익명 메서드의 개념을 이해해야 델리게이트와 람다식의
동작 원리를 이해하는 데 도움이 되니 모두 이해하는 편이 좋겠다
반응형