전체 코드

enum ItemType { Weapon, Armor, Amulet, Ring }
enum Rarity { Normal, Uncommon, Rare }

class Item
{
    public ItemType ItemType;
    public Rarity Rarity;
}

class Program
{
    static List<Item> _items = new List<Item>();

    static Item FindItem(Func<Item, bool> selector)
    {
        foreach (Item item in _items)
        {
            if (selector(item))
                return item;
        }
        return null;
    }

    static void Main(string[] args)
    {
        _items.Add(new Item { ItemType = ItemType.Weapon, Rarity = Rarity.Normal });
        _items.Add(new Item { ItemType = ItemType.Armor, Rarity = Rarity.Uncommon });
        _items.Add(new Item { ItemType = ItemType.Ring, Rarity = Rarity.Rare });

        Item item = FindItem((Item item) => item.ItemType == ItemType.Weapon);
        Console.WriteLine(item?.ItemType);  // Weapon 출력
    }
}

🔔 람다식이란?

람다식(Lambda Expression)일회용 함수를 간단하게 표현할 수 있는 C# 문법입니다.

  • 이름 없는 함수(익명 함수)를 간단하게 정의
  • 함수 포인터처럼 사용 가능
  • 대리자(Delegate) 또는 이벤트(Event)에 등록할 때 유용

❓ 람다식이 필요한 이유

아이템 리스트에서 특정 조건에 맞는 아이템을 찾는 함수를 만든다고 가정해봅시다.

기존 방식

static Item FindWeapon()
{
    foreach (Item item in _items)
    {
        if (item.ItemType == ItemType.Weapon)
            return item;
    }
    return null;
}
  • 조건마다 새로운 함수를 계속 만들어야 함 (무기, 갑옷, 반지 등등)
  • 조건 추가할 때마다 함수 폭발 (N가지 조건 = N개의 함수)

🔥 더 나은 방법 - 조건을 "함수"로 넘기기

delegate bool ItemSelector(Item item);

static Item FindItem(ItemSelector selector)
{
    foreach (Item item in _items)
    {
        if (selector(item))
            return item;
    }
    return null;
}
  • 아이템 찾기 로직은 FindItem 하나로 통합
  • 조건 검사 함수만 따로 작성
static bool IsWeapon(Item item) => item.ItemType == ItemType.Weapon;
  • 호출 시 조건 함수 전달
Item item = FindItem(IsWeapon);

😵‍💫 여전히 문제

  • 조건 함수(IsWeapon, IsArmor 등)를 매번 정의해야 함
  • 조건이 단순한 경우, 함수까지 만드는 게 너무 번거로움

💡 해결책 - 람다식으로 한 방에 해결

Item item = FindItem((Item item) => { return item.ItemType == ItemType.Weapon; });
  • 함수를 따로 만들 필요 없이, 조건 검사 로직을 즉석에서 정의
  • 필요할 때 바로 작성하고, 함수 정의 없이 일회용 함수로 사용


📥 람다식 기본 문법

형태예시
입력과 본체 분리(매개변수) => { 본문 }
매개변수 타입 생략 가능item => item.ItemType == ItemType.Weapon
return 생략 가능x => x + 1
매개변수 2개(a, b) => a + b
매개변수 없을 때() => Console.WriteLine("Hello")

📦 람다식 + Func/Action 조합

✅ Func

  • 반환값이 있는 경우
  • 이미 C#에 기본 제공되는 제네릭 대리자 (직접 delegate 선언 필요 없음)
Func<Item, bool> selector = item => item.Rarity == Rarity.Rare;

✅ Action

  • 반환값이 없는 경우
  • 함수에 전달할 매개변수만 필요할 때 사용
Action<Item> printer = item => Console.WriteLine(item.ItemType);

✅ Func vs Action vs Predicate

타입설명예시
Func입력 O, 반환 OFunc<int, int, int> (두 수 더하기)
Action입력 O, 반환 XAction<string> (문자열 출력)
Predicate입력 O, 반환 boolPredicate<Item> (조건 검사)

🌐 예제: Func 활용

Func<Item, bool> isRare = item => item.Rarity == Rarity.Rare;
Item rareItem = FindItem(isRare);

🌐 예제: Action 활용

Action<Item> printItem = item => Console.WriteLine($"{item.ItemType}, {item.Rarity}");
_items.ForEach(printItem);

📊 정리 표 - 익명 함수 vs 람다식 vs 일반 함수

방식설명예시
일반 함수이름 있는 함수로 재사용 목적bool IsWeapon(Item item)
익명 함수이름 없이 즉석 생성delegate(Item i) { return i.ItemType == ItemType.Weapon; }
람다식가장 간결하고 유연한 형태item => item.ItemType == ItemType.Weapon

📌 람다식 사용 패턴

상황패턴
리스트 검색FindItem(item => item.Rarity == Rarity.Rare)
리스트 정렬items.Sort((a, b) => a.Rarity.CompareTo(b.Rarity))
이벤트 핸들러 등록button.Click += (s, e) => Console.WriteLine("클릭!")

🏷️ 람다식과 클로저(Closure)

람다식은 외부 변수를 캡처해서 사용할 수 있음.

int threshold = 100;
Func<int, bool> isBig = x => x > threshold;
  • threshold는 람다식 외부에 있지만, 내부에서 사용 가능 = 클로저

profile
李家네_공부방

0개의 댓글