C# Lambda-Expression | λλ€μ
π« Q
- λλ€μ ?
- λλ€μμ μ μΈνκ³ μ¬μ©νλ λ°©λ²
- λ¬Έ νμμ λλ€μμ μμ±νκ³ μ¬μ©νλ λ°©λ²
- μ νΈλ¦¬
π« Lambda-Expression | λλ€μ
μ΅λͺ
-λ©μλ
λ₯Ό λ§λλ λ νλμ λ°©λ².
λλ€μμΌλ‘ λ§λλ μ΅λͺ
λ©μλλ 무λͺ
-ν¨μ(Anonymous Function)
λΌλ μ΄λ¦μΌλ‘ λΆλ₯Έλ€.
𫧠Lambda-Expression ꡬν
(맀κ°λ³μ) => μ
κ°μ λͺ¨μμΌλ‘ λ§λ λ€.
=>
λ μ
λ ₯ μ°μ°μ
(νΉμ λλ€ μ°μ°μ(Lambda Operator)).
=>
λ₯Ό μ€μ¬μΌλ‘ μΌμͺ½μλ 맀κ°λ³μ, μ€λ₯Έμͺ½μλ μμ΄ μμΉ.
κ·Έμ μΌμͺ½ λ§€κ° λ³μλ₯Ό μ€λ₯Έμͺ½ μμ μ λ¬νλ μν .
1
(int x, int y) => x + y
𫧠Type-Inference | νμ μΆλ‘ (νμ μ μΆ)
C# μ»΄νμΌλ¬λ μ½λλ₯Ό νμΈ΅ λ κ°κ²°νκ² λ§λ€ μ μλλ‘ νμ
μΆλ‘ (νμ μ μΆ) (Type-Inference)
λ₯Ό μ§μνλ€.
νμ
μΆλ‘ μ μ΄μ©νλ©΄ λλ€μμμ λ§€κ° λ³μμ νμ
μ μ κ±°ν μ μλ€.
1
2
3
4
delegate int MyDelegate(int x, int y);
// C# μ»΄νμΌλ¬κ° `delegate`μ μ μΈ μ½λλ‘λΆν° 무λͺ
ν¨μμ λ§€κ° λ³μ νμ
μ μΆλ‘ ν΄λΈλ€.
MyDelegate myDelegate = (x, y) => x + y;
𫧠Lambda-Expression Why?
λλ€μμΌλ‘ λ§λλ 무λͺ ν¨μλ, λ리μλ₯Ό μ΄μ©ν μ΅λͺ λ©μλλ³΄λ€ κ°κ²°νλ€.
λ λ²κ±°λ‘μ΄ λ°©λ²κ³Ό λ κ°κ²°ν λ°©λ²μ΄ λμμ μ‘΄μ¬νλ μ΄μ ?
λ리μλ₯Ό μ΄μ©ν μ΅λͺ λ©μλλC# 2.0
μμ λμ , λλ€μμC# 3.0
μμ λμ .
νμ νΈνμ±μ μ μ§νκΈ° μν΄ λ κ°μ§ λ°©λ²μ λͺ¨λ μ§μ.
1
2
3
4
5
6
7
delegate int MyDelegate(int x, int y);
// μ΅λͺ
-λ©μλ
MyDelegate myDelegate = delegate (int x, int y) { return x + y; };
// λλ€μ
MyDelegate myDelegate = (x, y) => x + y;
𫧠Statement Lambda | λ¬Έ νμμ λλ€μ
μ νμμ λλ€μ
λ =>
μ°μ°μμ μ€λ₯ΈνΈμ μμ μ¬μ©.
λ¬Έ νμμ λλ€μ
μ =>
μ°μ°μμ μ€λ₯ΈνΈμ μ€κ΄νΈ({}
)λ₯Ό μ¬μ©νμ¬ μ½λ λΈλ‘μ μμ±.
μ¬λ¬ μ€μ μ½λλ₯Ό μ¬μ©ν μ μμΌλ©°, return
ν€μλλ₯Ό μ¬μ©νμ¬ λ°νκ°μ μ§μ ν μ μλ€.
λ°ν νμμ΄ μλ 무λͺ
-ν¨μλ₯Ό λ§λ€ μ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
(int x, int y) => { /* ... */ }
(int x, int y) =>
{
// ...
return x + y;
}
( ) => { /* ... */ }
( ) =>
{
// ...
return 0;
}
π« Expression-Tree | μ-νΈλ¦¬
μμ νΈλ¦¬λ‘ ννν μλ£ κ΅¬μ‘°.
μλ₯Ό λ€μ΄ 1 * 2 + (7 - 8)
κ°μ μμ νΈλ¦¬λ‘ νννλ©΄ μλκ³Ό κ°λ€.
1
2
3
4
5
+
/ \
* -
/ \ / \
1 2 7 8
μ νΈλ¦¬μμ μ°μ°μλ λΆλͺ¨ λ
Έλκ° λλ©°, νΌμ°μ°μλ μμ λ
Έλκ° λλ€.
μ΄λ κ² μ νΈλ¦¬λ‘ ννλ μμ νΈλ¦¬μ μ λ
ΈλλΌλ¦¬ κ³μ°ν΄μ μ°¨λ‘μ°¨λ‘ λ£¨νΈκΉμ§ μ¬λΌκ°λ©΄ μ 체 μμ κ²°κ³Όλ₯Ό μ»μ μ μλ€.
𫧠Expression-Tree Why?
μμ ν C# μ»΄νμΌλ¬λ μλμ§λ§,
νλ‘κ·Έλλ¨Έκ° μ½λ μμμ μ§μ μ νΈλ¦¬λ₯Ό 쑰립νκ³ μ»΄νμΌν΄μ μ¬μ©ν μ μλ κΈ°λ₯μ μ 곡.
λ€μ λ§ν΄, νλ‘κ·Έλ¨ μ€ν μ€μ λμ μΌλ‘ 무λͺ
ν¨μλ₯Ό λ§λ€μ΄ μ¬μ©ν μ μκ² ν΄μ€λ€λ μ΄μΌκΈ°.
μ νΈλ¦¬ μλ£ κ΅¬μ‘°λ μ»΄νμΌλ¬λ μΈν°ν리ν°λ₯Ό μ μνλ λ°λ μμ©.
μ»΄νμΌλ¬λ νλ‘κ·Έλλ° μΈμ΄μ λ¬Έλ²μ λ°λΌ μμ±λ μμ€ μ½λλ₯Ό λΆμν΄μ μ νΈλ¦¬λ‘ λ§λ ν, μ΄λ₯Ό λ°νμΌλ‘ μ€ν νμΌμ λ§λ λ€.
π« Expression
𫧠Expression Class
Expression ν΄λμ€μ μμ΄λ€(νμ ν΄λμ€λ€).
μ νΈλ¦¬λ₯Ό λ€λ£¨λλ° νμν ν΄λμ€.
System.Linq.Expressions
λ€μμ€νμ΄μ€μ μ μλμ΄ μλ€.
Expression ν΄λμ€λ μ νΈλ¦¬λ₯Ό ꡬμ±νλ λ
Έλλ₯Ό νν
κ·Έλμ Expressionμ μμλ°λ νμ ν΄λμ€λ€ μμ μ νΈλ¦¬μ κ° λ
Έλλ₯Ό νν
Expression ν΄λμ€λ νμ ν΄λμ€λ€μ κ°μ²΄λ₯Ό μμ±νλ μν λ λ΄λΉ
νμ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±νλ μ μ ν©ν 리 λ©μλλ₯Ό μ 곡.
Expression ν΄λμ€ μ체λ μΆμ ν΄λμ€μ΄λ―λ‘ μ§μ μΈμ€ν΄μ€λ₯Ό μμ±ν μλ μλ€.
𫧠Expression ꡬν
Expressin ν΄λμ€μ μ μ ν©ν 리 λ©μλλ₯Ό ν΅ν κ°μ²΄ μμ±.
νλ‘κ·Έλλ¨Έλ κ° λ
Έλκ° μ΄λ€ νμ
μΈμ§ μ κ²½ μ°μ§ μκ³ κ±°μΉ¨μμ΄ Expression νμμ μ°Έμ‘°λ₯Ό μ μΈν΄μ μ¬μ©ν μ μλ€.
νμν κ²½μ°μλ κ° μΈλΆ νμμΌλ‘ νλ³νμ νλ©΄ λλκΉ.
μ΄κ²μ΄ ν©ν 리 λ©μλ ν¨ν΄μ 맀λ ₯.
1
2
3
4
5
Expression const1 = Expression.Constant(1);// μμ ννμ κ°μ²΄ μμ±
Expression param1 = Expression.Parameter(typeof(int), "x"); // 맀κ°λ³μ ννμ κ°μ²΄ μμ±
Expression exp = Expression.Add(const1, param1); // λ§μ
ννμ κ°μ²΄ μμ±
// '1 + x' λ₯Ό λνλ΄λ μ νΈλ¦¬
𫧠Expression μ»΄νμΌ/μ€ν
μ νΈλ¦¬λ κ²°κ΅ βμβμ νΈλ¦¬λ‘ ννν κ²μ λΆκ³Ό.
λ€μ λ§ν΄, μ€ν κ°λ₯ν μνκ° μλλΌ κ·Έμ βλ°μ΄ν°β μνμ λ¨Έλ¬Όλ¬ μλ€λ λ§.
μμ μ νΈλ¦¬ μλ£ κ΅¬μ‘° μμ μ μλμ΄ μλ μμ μ€νν μ μμΌλ €λ©΄ λλ€μμΌλ‘ μ»΄νμΌλμ΄μΌ νλ€.
λλ€μμΌλ‘μ μ»΄νμΌμ Expression<TDelegate>
ν΄λμ€λ₯Ό μ΄μ©νλ€.
(Expression
<- LambdaExpression
<- Expression<TDelegate>
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Expression const1 = Expression.Constant(1);
Expression param1 = Expression.Parameter(typeof(int), "x");
Expression exp = Expression.Add(const1, param1);
// λλ€μ LambdaExpression (μ ννλ νμ ν΄λμ€μΈ Expression<TDelegate>) μμ±
Expression<Func<int, int>> lambda1 =
Expression.Lambda<Func<int, int>>( // λ°νκ°μ΄ intμ΄κ³ 맀κ°λ³μκ° intμΈ λλ€μμ λ§λλλ€.
exp,
new ParameterExpression[] { (ParameterExpression)param1 });
// μ€νκ°λ₯ν μ½λλ‘ μ»΄νμΌ
Func<int, int> compiledExp = lambda1.Compile();
// μ»΄νμΌλ λλ€μμ μ€ν
Console.WriteLine(compiledExp(3)); // Output : 4
𫧠Expression λλ€μ νμ©
λλ€μμ μ΄μ©νλ©΄ λ κ°λ¨νκ² μ νΈλ¦¬λ₯Ό λ§λ€ μ μλ€.
λ€λ§ μ΄ κ²½μ°μλ βλμ μΌλ‘β μ νΈλ¦¬λ₯Ό λ§λ€κΈ°λ μ΄λ €μμ§λ€.
Expression νμμ βλΆλ³ (Immutable)βμ΄κΈ° λλ¬Έμ, ν λ² μΈμ€ν΄μ€λ₯Ό λ§λ€λ©΄ μμ ν μ μλ€.
1
2
3
4
Expression<Func<int, int>> lambda2 = (x) => 1 + x;
Func<int, int> compiledExp = lambda2.Compile();
Console.WriteLine(compiledExp(3)); // Output : 4
𫧠Expression So?
μ νΈλ¦¬λ μ½λλ₯Ό βλ°μ΄ν°βλ‘μ¨ λ³΄κ΄ν μ μλ€.
νμΌμ μ μ₯ν μλ μκ³ λ€νΈμν¬λ₯Ό ν΅ν΄ λ€λ₯Έ νλ‘μΈμ€μ μ λ¬ν μλ μλ€.
μ¬μ§μ΄ μ½λλ₯Ό λ΄κ³ μλ μ νΈλ¦¬ λ°μ΄ν°λ₯Ό λ°μ΄ν° λ² μ΄μ€ μλ²μ 보λ΄μ μ€νμν¬ μλ μλ€.
λ°μ΄ν° λ² μ΄μ€ μ²λ¦¬λ₯Ό μν μ νΈλ¦¬λ LINQμμ μ¬μ©λλ€
LINQλ₯Ό μ΄ν΄νλ €λ©΄ λλ€μκ³Ό μ νΈλ¦¬λ₯Ό μ΄ν΄νκ³ μμ΄μΌνλ€.
𫧠Expression-Bodied Member | μ λ³Έλ¬Έ λ©€λ²
βλ©μλ, μμ±(μΈλ±μ), μμ±μ, μ’
λ£μβμ 곡ν΅λ νΉμ§?
λͺ¨λ ν΄λμ€μ λ©€λ²λ‘μ λ³Έλ¬Έμ΄ μ€κ΄νΈλ‘ λ§λ€μ΄μ Έ μλ€.
μ΄λ¬ν λ©€λ²μ λ³Έλ¬Έμ μ(Expression)λ§μΌλ‘ ꡬννλ κ²μ΄ κ°λ₯νλ€.
λ©€λ² => μ
ννλ‘ κ΅¬ννλ€.
μ΄λ κ² μμΌλ‘ ꡬνλ λ©€λ²λ₯Ό μ λ³Έλ¬Έ λ©€λ²(Expression-Bodied Member)
λΌκ³ λΆλ₯Έλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class MyClass
{
private List<int> list = new List<int>();
// λ©μλ
public void Add(int value) => list.Add(value);
// μ½κΈ° μ μ© μμ±
public int Capacity => list.Capacity;
// μ½κΈ° / μ°κΈ° κ°λ₯ν μμ±, μΈλ±μ [1]
public int this[int index]
{
get => list[index];
set => list[index] = value;
}
// μΈλ±μ [2]
public int this[int index] => list[index];
// μμ±μ, μ’
λ£μ
public MyClass(int value) => this.value = value;
~MyClass() => Console.WriteLine("μλ©Έμ νΈμΆ");
}
π« λ©λͺ¨
Ξ»-Expression
Ξ»
λ κ·Έλ¦¬μ€ λ¬ΈμμμL
μ ν΄λΉνλ λ¬Έμ- μλ‘ μ‘° μ²μΉλ μ΄ λ¬Έμλ₯Ό ν¨μ νκΈ°λ₯Ό μν κΈ°νΈλ‘
^
λ₯Ό μ¬μ©νλλ°, μ΄λ νλ¦°ν°μμ μ΄λ €μμ΄ μμ΄ Ξ»λ‘ λ°κΏ¨λ€κ³ ν¨
- μλ‘ μ‘° μ²μΉλ μ΄ λ¬Έμλ₯Ό ν¨μ νκΈ°λ₯Ό μν κΈ°νΈλ‘
=>
λ₯Ό νμ΄ν μ°μ°μλΌκ³ λ λΆλ₯Έλ€.- μ΄ κ²½μ°,
=>
λ₯Ό μ΄μ©ν μμ νμ΄ν ν¨μλΌκ³ λΆλ₯Έλ€.
- μ΄ κ²½μ°,
- βμ΄κ²μ΄ C#μ΄λ€.β, βMSDNβ
- LINQ
- Factory-Pattern
- TODO: νλ‘κ·Έλλ° μΈμ΄λ‘ κ³Ό μ°κ΄μ§μ΄ (μνΈλ¦¬)
𫧠Lambda-Expression 배경
μλ‘ μ‘° μ²μΉ(Alonzo Church)
1936λ
μ κ³ μν λλ€ κ³μ°λ²(Lambda Calculus : λλ€ λμ)μμ μ λ.
- λλ€ κ³μ°λ² :
- μν κΈ°μ΄λ‘ μ μ°κ΅¬νλ μ€, λΆλͺ νκ³ κ°κ²°ν λ°©λ²μΌλ‘ ν¨μλ₯Ό λ¬μ¬νκΈ° μν΄ κ³ μ
- ν¬κ² ν¨μμ μ μμ λ³μ, κ·Έλ¦¬κ³ ν¨μμ μ μ©μΌλ‘ ꡬμ±
- μ΄ κ³μ°λ²μμλ λͺ¨λ κ²μ΄ ν¨μλ‘ μ΄λ£¨μ΄μ Έ μμ, μ¬μ§μ΄ β0, 1, 2 β¦β κ°μ μ«μλ ν¨μλ‘ νν
- λ°λΌμ λλ€ κ³μ°λ²μμλ μ΄λ€ κ°μ λ³μμ λμ νκ³ μΆμΌλ©΄ ν¨μλ₯Ό λ³μμ λμ νλ©°, μ΄κ²μ ν¨μμ μ μ©μ΄λΌκ³ λΆλ¦
μ μμλ μ‘΄ 맀카μ(John McCarthy)
.
μ΄κ²μ λ¨μν μν μ΄λ‘ μ κ·ΈμΉμ§ μκ³ , νλ‘κ·Έλλ° μΈμ΄μ λμ
ν μ μκ² λ€λ μμ΄λμ΄λ₯Ό μ μ.
50λ
λ λ§μ LISP
λΌλ μΈμ΄λ₯Ό κ°λ°.
μ΄ν λλ€ κ³μ°λ²μ κ°λ
μ μ΄ν λ€λ₯Έ νλ‘κ·Έλλ° μΈμ΄μλ λμ
λμμΌλ©°,
C#, C++, Java, Python κ°μ μ£Όλ₯ νλ‘κ·Έλλ° μΈμ΄λ λλΆλΆ λλ€μμ μ§μ.