우리가 코드를 만들다 보면 일일이 확인하는 함수를 만든다거나 찾는 함수를 만들 때가 있는데
이러한 함수들은 찾는것에 종류등에 따라 여러개 만들어야할 수 있는 상황이 생긴다.
그래서 종류에따라 함수들을 만들면 너무 비효율적인데 이러한 상황에서 사용할 수 있는 문법이 Lamda식이다.
간단히 Lamda식을 설명해보자면
코드로 예를 들자면,
1.Item 클래스 존재
1-1. 종류:Weapon,Armor,Amulet,Ring
1-2. 희귀도: Normal,Uncommon,Rare
enum ItemType
{
Weapon,
Armor,
Amulet,
Ring
}
enum Rarity
{
Normal,
Uncommon,
Rare,
}
class Item
{
public ItemType ItemType;
public Rarity Rarity;
}
2.메인함수
2-1.Item의 리스트
2-2.Item의 delegate
2-3.FindItem 함수
2-4.메인함수 익명함수,람다식
static List<Item> _items = new List<Item>();
delegate bool ItemSelector(Item item);
static Item FindItem(ItemSelector selector)
{
foreach(Item item in _items)
{
if(selector(item))
return item;
}
return null;
}
static void Main(string[] args)
{
//Lamda : 일회용 함수를 만드는데 사용하는 문법 ( 함수를 일일이 만들지않고 빠르게 만드는 방법)
//왜 필요한지 ?
_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(IsWeapon);
// Anonymous Function : 무명,익명 함수
Item item2 = FindItem(delegate (Item item) { return item.ItemType == ItemType.Weapon; });
//Lamda식
Item item3 = FindItem((Item item) => { return item.ItemType == ItemType.Weapon; });
}
또한,일회용 함수도 재사용이 가능하다.
//delegate도 객체를 만들 수 있었다. 객체에 람다식을 넣고 밑에처럼 재사용 하면 된다.
ItemSelector selector = new ItemSelector((Item item) => { return item.ItemType == ItemType.Weapon; });
Item item = Finditem(selector); //재사용
위에 방법처럼 대리자를 이용하여 사용할 인자를 넘겨줄 함수의 형식을 선언해도 되지만 더욱 간편히 일반화하여 사용하는 방법이 있다.
static List<Item> _items = new List<Item>();
//앞으로 반환형식이 1개있고 입력하는 형식1개인 대리자는 모두 MyFunc로 처리
delegate Return MyFunc<T,Return>(T item);
//인자 개수가 다르면 다른버전을 계속 만들면 된다.
delegate Return MyFunc<T1,T2,Return>(T1 t1,T2 t2, item);
static Item FindItem(MyFunc<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 });
MyFunc<Item,bool> selector = new MyFunc<Item,bool>((Item item) => { return item.ItemType == ItemType.Weapon; });
//위의 코드에서 new를 안써도 괜찮다.
//MyFunc<Item,bool> selector = (Item item) => { return item.ItemType == ItemType.Weapon; };
Item item = Finditem(selector); //재사용
}
맨 위에 ItemSelector처럼 특정 기능만 하는게아니라 MyFunc로 인자에 따른 처리로 만들어두면 일반화하기 쉬운데 이게 C#에서 따로 구현이 되어 있다.
static Item FindItem(Func<Item,bool> selector)
{
foreach(Item item in _items)
{
if(selector(item))
return item;
}
return null;
}
//Func는 위에 만든 MyFunc와 같은 기능을하는데 T1~T16 버전까지 있고 반환형이 있는 형식
MyFunc<Item,bool> selector = (Item item) => { return item.ItemType == ItemType.Weapon; };
//Action은 void반환 형식의 형식
Action<Item>
정리 : delegate를 직접 선언하지 않아도, 이미 만들어진 기능이 있다.
반환 타입이 있을 경우 Func
반환 타입이 없을 경우 Action