π» Programming Language/C#
38. λλ€μ(Lambda Expression)
S.Honey
2022. 4. 8. 09:14
λλ€μ
:μ΅λͺ λ©μλ
λ₯Ό λ§λ€κΈ° μν΄ μ¬μ©νλ μλλ€μ
μΌλ‘ λ§λ€μ΄μ§μ΅λͺ λ©μλ
λ₯Όλ¬΄λͺ ν¨μ(Anonymous Function)
λΌκ³ νλ€.
λλ€μ μ μΈ νμ
λ§€κ°λ³μ λͺ©λ‘ => μ
=>
μ°μ°μλ₯Ό μ λ ₯ μ°μ°μλΌκ³ νλ€.
delegate int AAA(int x, int y);
static void Main(string[] args){
AAA aaa = (int x,int y) => x + y;
}
(int x, int y) => x + y
λΌλμ΅λͺ λ©μλ
κ°delegate
μΈaaa
μ μ λ¬λκ³ μλ λͺ¨μ΅μμ μ½λλ λ€μκ³Ό κ°μ΄ λ°κΏμ μ¬μ© κ°λ₯
AAA aaa = (x, y) => x + y;
delegateμ μΈμμ νμ μ΄ μ μΈλμ΄ μκΈ°μ κ°λ₯
μμ μ΅λͺ λ©μλ(무λͺ ν¨μ)λ κΈ°μ‘΄μ μ΅λͺ λ©μλλ₯Ό μ¬μ©νλ κ² λ³΄λ€ κ°μν λμλ€.
κΈ°μ‘΄ λΈλ¦¬κ²μ΄νΈλ₯Ό μ¬μ©νλ λ°©μ
delegate int AAA(int x, int y);
static void Main(string[] args){
AAA aaa = delegate(int x, int y)
{
return x+y;
}
}
μ½λ μ¬μ© μμ 1
using System.Collections;
namespace LambdaEx
{
class Program
{
delegate int Sum(int x, int y);
static void Main(string[] args)
{
Sum sum = (x, y) => x + y;
Console.WriteLine($"{sum(10, 20)}");
}
}
}
λλ€μμ λ λ€λ₯Έ νν
- μ μΈνμλ€ .. ? => λ€μνκ² μ¬μ©λ λ―
λ§€κ°λ³μλͺ©λ‘ => {
μ€νμ½λ ...
}
λ리μ μΈμ€ν΄μ€ = () => { ... μ€νμ½λ ... }
// λ§€κ°λ³μκ° μλ 무λͺ
ν¨μ
λ리μ μΈμ€ν΄μ€ = (λ§€κ°λ³μ) => { ... μ€νμ½λ ... }
// λ§€κ°λ³μκ° μλ 무λͺ
ν¨μ
μ¬μ©μμ μ½λ
using System.Collections;
namespace LambdaEx
{
class Program
{
delegate string SumString(string[] args);
static void Main(string[] args)
{
SumString ss = (str) =>
{
string result = "";
foreach (string s in str)
{
result += s;
}
return result;
};
Console.WriteLine(ss(args));
}
}
}
.exe
νμΌμ μ€νμμΌ μ λ ₯μ μ£Όλ©΄ ν΄λΉ μ λ ₯μ μ΄μ΄λΆμΈstring
κ²°κ³Όλ₯Ό μΆλ ₯.
λλ€μ μ¬μ©μμ μ½λ μΆκ°
class Program
{
delegate int Calculate(int a , int b);
delegate string Concatenate(string[] strs);
static void Main(string[] args)
{
// μ νμμ λλ€μ
Calculate cal1 = (a, b) => a + b;
Console.WriteLine("{0} + {1} = {2}",3,4,cal1(3,4));
// λ¬Έ νμμ λλ€μ
Concatenate concat = (arr) =>
{
string result = "";
foreach (string str in arr)
{
result += str;
}
return result;
};
string[] txt = {"μλ²μ§κ°","λ°©μ", "λ€μ΄κ°μ λ€" };
Console.WriteLine("μλ²μ§κ° λ°©μ λ€μ΄κ°μ λ€ => {0}", concat(txt));
}
}
Output
3 + 4 = 7
μλ²μ§κ° λ°©μ λ€μ΄κ°μ λ€ => μλ²μ§κ°λ°©μλ€μ΄κ°μ λ€
Func μ Action μ μ¬μ©ν 무λͺ ν¨μ μ μΈ
- κΈ°μ‘΄ μ΅λͺ
ν¨μ νΉμ 무λͺ
ν¨μλ₯Ό μ¬μ©νλ €λ©΄ λ§€λ² λ³κ°μ λΈλ¦¬κ²μ΄νΈλ₯Ό μ μΈν΄μΌνλ λ²κ±°λ‘μμ΄ μλ€.
- MSλ μ΄λ₯Ό ν΄κ²°νκΈ° μν΄
.Net
νλ μμν¬μFunc
μAction
λΈλ¦¬κ²μ΄νΈλ₯Ό 미리 μ μΈ ν΄λμλ€. Func λΈλ¦¬κ²μ΄νΈ
=> κ²°κ³Όλ₯Ό λ°ννλ λ©μλλ₯Ό μ°Έμ‘°νκΈ° μν΄Action λΈλ¦¬κ²μ΄νΈ
=> κ²°κ³Όλ₯Ό λ°ννμ§ μλ λ©μλλ₯Ό μ°Έμ‘°νκΈ° μν΄
- MSλ μ΄λ₯Ό ν΄κ²°νκΈ° μν΄
Func λΈλ¦¬κ²μ΄νΈ
- μ μΈνμ
public delegate TResult Func<out TResult>()
public delegate TResult Func<in T1, out TResult>(T arg)
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2)
...
16κ° μΈμλ₯Ό κ°μ§ κ²κΉμ§..
- λͺ¨λ
Func
λΈλ¦¬κ²μ΄νΈμ νμ λ§€κ°λ³μ μ€ κ°μ₯ λ§μ§λ§μ μλ κ²μ΄ λ°ννμμ΄λ€.
- κ°λ¨ν μ¬μ©μμ
Func<int> func1 = () => 10;
// μ
λ ₯ λ§€κ°λ³μλ μμΌλ©° 무쑰건 intνκ°μΈ 10μ λ°ν
Console.WriteLine(func1()); // 10 μΆλ ₯
Func<int, int> func2 = (x) => x * 2;
//μ
λ ₯ λ§€κ°λ³μλ int νμ νλ, λ°ν νμλ int
Console.WriteLine(func2(3)); // 6 μΆλ ₯
Func<int,int,int> func3 = (x,y) => x + y;
//μ
λ ₯ λ§€κ°λ³μλ int νμ λ, λ°ν νμλ int
Console.WriteLine(func3(2,3)); // 5 μΆλ ₯
Func λΈλ¦¬κ²μ΄νΈ μ¬μ© μμ μ½λ
using System;
namespace FuncTest
{
class MainApp
{
static void Main(string[] args)
{
Func<int> func1 = () => 10;
// μ
λ ₯ λ§€κ°λ³μλ μμΌλ©° 무쑰건 intνκ°μΈ 10μ λ°ν
Console.WriteLine(func1()); // 10 μΆλ ₯
Func<int, int> func2 = (x) => x * 2;
//μ
λ ₯ λ§€κ°λ³μλ int νμ νλ, λ°ν νμλ int
Console.WriteLine(func2(3)); // 6 μΆλ ₯
Func<int, int, int> func3 = (x, y) => x + y;
//μ
λ ₯ λ§€κ°λ³μλ int νμ λ, λ°ν νμλ int
Console.WriteLine(func3(2, 3)); // 5 μΆλ ₯
}
}
}
Output
10
6
5
Action λΈλ¦¬κ²μ΄νΈ
Action
λΈλ¦¬κ²μ΄νΈλFunc
μ κ±°μ λΉμ·νλ€.- μ°¨μ΄μ μ΄λΌ νλ©΄
Action
λΈλ¦¬κ²μ΄νΈμ κ²½μ°μλ λ°ν νμμ΄ μλ€.
- μ μΈνμ
public delegate void Action<>()
public delegate void Action<in T>(T1 arg)
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2)
...
16κ° μΈμλ₯Ό κ°μ§ κ²κΉμ§..
Action λΈλ¦¬κ²μ΄νΈ μ¬μ© μμ μ½λ
using System;
namespace ActionTest
{
class MainApp
{
static void Main(string[] args)
{
Action act1 = () => Console.WriteLine("Action()");
act1();
int result = 0;
Action<int> act2 = (x) => result = x * x;
act2(3);
Console.WriteLine("result : {0}", result);
Action<double, double> act3 = (x, y) =>
{
double pi = x / y;
Console.WriteLine("Action<T1, T2>({0}, {1}) : {2}", x, y, pi);
};
act3(22.0, 7.0);
}
}
}
Output
Action()
result : 9
Action<T1, T2>(22, 7) : 3.142857142857143
Func & Action ν΅ν© μμ μ½λ
using System;
class MainApp
{
static void Main(string[] args)
{
Func<int> func1 = () => 10;
// μ
λ ₯ λ§€κ°λ³μλ μμΌλ©° 무쑰건 intνκ°μΈ 10μ λ°ν
Console.WriteLine(func1()); // 10 μΆλ ₯
Func<int, int> func2 = (x) => x * 2;
//μ
λ ₯ λ§€κ°λ³μλ int νμ νλ, λ°ν νμλ int
Console.WriteLine(func2(3)); // 6 μΆλ ₯
Func<int, int, int> func3 = (x, y) => x + y;
//μ
λ ₯ λ§€κ°λ³μλ int νμ λ, λ°ν νμλ int
Console.WriteLine(func3(2, 3)); // 5 μΆλ ₯
Action act1 = () => Console.WriteLine("Action()");
act1();
int result = 0;
Action<int> act2 = (x) => result = x * x;
act2(3);
Console.WriteLine("result : {0}", result);
Action<double, double> act3 = (x, y) =>
{
double pi = x / y;
Console.WriteLine("Action<T1, T2>({0}, {1}) : {2}", x, y, pi);
};
act3(22.0, 7.0);
}
}
Output
10
6
5
Action()
result : 9
Action<T1, T2>(22, 7) : 3.142857142857143
μ νΈλ¦¬ (Expression Tree)
μ
μνΈλ¦¬
λ‘ νννμλ£κ΅¬μ‘°
Expression
ν΄λμ€μ νμν΄λμ€λ€μ μ΄μ©ν΄ μνΈλ¦¬λ₯Ό ꡬμ±νλ€.
ν©ν 리 λ©μλ(Factory Method)
ν©ν 리 λ©μλλ ν΄λμ€μ μΈμ€ν΄μ€λ₯Ό μμ±νλ μΌμ λ΄λΉνλ λ©μλλ₯Ό κ°λ¦¬ν€λ μ©μ΄μ΄λ€.
C#μλ κ°μ²΄λ₯Ό μμ±νλ μμ±μ λ©μλκ° μκΈ΄νμ§λ§ κ°λμ μ΄κ²λ§μΌλ‘ μΆ©λΆνμ§ μμ λκ° μλ€.
κ°μ²΄μ μμ±μ 볡μ‘ν λ
Όλ¦¬κ° νμν κ²½μ°, κ°μ²΄ μμ± κ³Όμ μ λ³λμ λ©μλμ ꡬνν΄ λμΌλ©΄ μ½λμ 볡μ‘λλ₯Ό μλΉν μ€μΌ μ μλ€.
Expression ν΄λμ€μ μ μ ν©ν 리 λ©μλλ€μ Expression ν΄λμ€μ νμ ν΄λμ€μΈ ConstantExpression,
BinaryExpression ν΄λμ€ λ±μ μΈμ€ν΄μ€λ₯Ό μμ±νλ κΈ°λ₯μ μ 곡ν¨μΌλ‘μ¨ μκ³ λ₯Ό μ€μ¬μ€λ€.
1*2+(x-y)
μμ νΈλ¦¬λ‘ λ§λ ν μ»΄νμΌ νλ μμ μ½λ
using System;
using System.Linq.Expressions;
namespace UsingExpressionTree
{
class MainApp
{
static void Main(string[] args)
{
// 1 * 2 + (x - y)
Expression const1 = Expression.Constant(1);
Expression const2 = Expression.Constant(2);
Expression leftExp = Expression.Multiply(const1, const2);
Expression param1 = Expression.Parameter(typeof(int)); // x λ₯Ό μν λ³μ
Expression param2 = Expression.Parameter(typeof(int)); // y λ₯Ό μν λ³μ
Expression rightExp = Expression.Subtract(param1, param2);
Expression exp = Expression.Add(leftExp, rightExp);
Expression<Func<int,int,int>> expression = Expression<Func<int,int,int>>.Lambda<Func<int,int,int>>(exp, new ParameterExpression[]
{
(ParameterExpression)param1,
(ParameterExpression)param2,
});
Func<int,int,int> func = expression.Compile();
//x = 7, y = 8
Console.WriteLine("1 * 2 + ({0} - {1}) = {2}", 7, 8, func(7,8));
}
}
}
Output
1 * 2 + (7 - 8) = 1
λλ€μμ μ΄μ©ν΄μ μ νΈλ¦¬λ₯Ό λ§λλ μμ μ½λ
using System;
using System.Linq.Expressions;
namespace UsingExpressionTree
{
class MainApp
{
static void Main(string[] args)
{
Expression<Func<int,int,int>> expression = (a,b) => 1 * 2 + (a - b);
Func<int,int,int> func = expression.Compile();
//x = 7, y = 8
Console.WriteLine("1 * 2 + ({0} - {1}) = {2}", 7, 8, func(7, 8));
}
}
}
Output
1 * 2 + (7 - 8) = 1
- μμ λ§λ μ½λμ λΉν΄μ ν¨μ¬ κ°λ¨νκ² κ°μ κ²°κ³Όλ₯Ό λμΆν μ μλ€.
- νμ§λ§ μ΄ κ²½μ°μλ
λμ μΌλ‘
μ νΈλ¦¬λ₯Ό λ§λ€κΈ°λ μ΄λ ΅λ€. Expression
νμμλΆλ³(Immutable)
μ΄κΈ° λλ¬Έμ ν λ² μΈμ€ν΄μ€κ° λ§λ€μ΄μ§κ³ λ νμλ λ³κ²½ν μ μκΈ° λλ¬Έμ΄λ€.