C#/이것이 C#이다
14장. 람다식
개발자엄지희
2023. 5. 18. 16:43
반응형
1. 람다식, 너는 어디에서 왔니?
람다 계산법: 어떤 값을 변수에 대입하고 싶으면, 함수를 변수에 대입
2. 처음 만나는 람다식
익명 메소드: 무명 함수로, 입력(매개 변수)와 출력(반환 값)을 가지고 있음
기본적인 람다식
매개_변수_목록 => 식
람다식 선언 예
delegate int Calculate(int a, int b);
static void Main(string[] args)
{
Calculate calc = (int a, int b) => a + b;
}
형식 유추로 더 간단하게!
Calculate calc = (a, b) => a + b;
만약에 대리자를 쓴다면
delegate int Calculate(int a, int b);
static void Main(string[] args)
{
Calculate calc = delegate(int a, int b)
{
return a + b;
};
}
대리자보다 람다식이 더 편하다! 하지만 람다식은 3.0에서야 도입되었기 때문에 대리자가 제거되진 않았다.
3. 문 형식의 람다식
(매개_변수_목록) => {
문장;
문장2;
문장3;
...
}
deleagate void DoSomething( );
// ...
static void Main(string[] args)
{
DoSomething DoIt = ( ) => {
Console.WriteLine("뭔가를");
Console.WriteLine("출력해보자.");
Console.WriteLine("이렇게!");
};
DoIt();
}
4. Func와 Action으로 더 간편하게 무명 함수 만들기
대부분의 경우 단 하나의 익명 메소드나 무명 함수를 만들기 위해 매번 별개의 대리자를 선언해야 합니다. 이러한 문제를 해결하기 위해, Func 대리자를 사용하면 결과를 반환하는 메소드를, Action 대리자를 사용하면 결과를 반환하지 않는 메소드를 참조할 수 있습니다.
1. Func 대리자 : 결과를 반환하는 메소드를 참조하기 위해
Func<int> func1 = () => 10; // 입력 매개 변수는 없으며, 무조건 10을 반환
Console.WirteLine(func1()); // 10 출력
Func<int, int> func2 = (x) => x*2; // 입력 매개 변수는 int 형식 하나, 반환 형식도 int
Console.WirteLine(func2(3)); // 6 출력
Func<int, int, int> func2 = (x, y) => x + y; // 입력 매개 변수는 int 형식 둘, 반환 형식도 int
Console.WirteLine(func2(2, 3)); // 5 출력
2. Action 대리자: 결과를 반환하지 않는 메소드를 참조하기 위해
Action act1 = () => Console.WrietLine("Action()");
act1();
int result = 0;
Action act2 = (x) => result = x * x;
act2(3);
Console.WriteLine($"result : {result}"); // 9를 출력
Action<double, double> act3 = (x, y) => {
double pi = x / y;
Console.WriteLine($"Action<T1, T2>({x}, {y}) : {pi}");
};
act3(22.0. 7.0);
5. 식 트리
식 트리: 식을 트리로 표현한 자료 구조
예를 들어, 연산자는 부모 노드가 되고 피연산자는 자식 노드가 됨
Expression 클래스
Expression 클래스를 상속받은 클래스들은 식 트리를 다루는 데 필요한 기능들을 사용할 수 있습니다.
Expression 클래스 자신은 abstract로 선언되어 자신의 인스턴스는 만들 수 없지만, 파생 클래스의 인스턴스를 생성하는 정적 팩토리 메소드를 제공하고 있습니다.
팩토리 메소드
클래스의 인스턴스를 생성하는 일을 담당하는 메소드
Expression const1 = Expression.Constant(1); // 상수 1
Expression param1 = Expression.Parameter(typeof(int), "x"); // 매개 변수 x
Expression exp = Expression.Add( const1, param1 ); // 1 + x
상수를 표현하는 ConstantExpression, 매개 변수를 표현하는 ParameterExpression 객체에 대해
덧셈 연산을 수행하는 BinaryExpression 객체를 선언
식 트리를 람다식으로 컴파일
식 트리는 "데이터"로서 보관된 것이기 때문에, 컴파일해주어야 함
Expression const1 = Expression.Constant(1); // 상수 1
Expression param1 = Expression.Parameter(typeof(int), "x"); // 매개 변수 x
Expression exp = Expression.Add( const1, param1 ); // 1 + x
Expression<Func<int, int>> lambda =
Expression<Func<int, int>>.lambda<Func<int, int>> (
exp,
new ParameterExpression[] { (ParameterExpression) param1 }
);
Func<int, int> compiledExp = lambda.Compile();
Console.WriteLine( compiledExp(3) ); // x = 3 이면 1 + x는 4 이므로 4 출력
람다식을 이용하면 더 간편하게 식 트리를 만들 수 있습니다.
만, "동적으로" 식 트리를 만들기는 어려워집니다.
6. 식으로 이루어지는 멤버
클래스의 멤버는 본문이 중괄호{ } 로 만들어져 있습니다. 이러한 멤버의 본문을 식으로만 구현하는 것을
식 본문 멤버(Expression-Bodied Member) 라고 합니다.
멤버 => 식;
class FriendList
{
private List<string> list = new List<string>();
public void Add(string name) => list.Add(name);
public void Remove(string name) => list.Remove(name);
public FriendList() => Console.WriteLine("FriendList()"); // 생성자
~FriendList() => Console.WriteLine("~FriendList()"); // 종료자
public int Capacity => list.Capacity; // 읽기 전용 속성
public string this[int index] => list[index]; // 읽기 전용 인덱서
public int Capacity // 속성
{
get => list.Capacity;
set => list.Capacity = value;
}
public string this[int index] // 인덱서
{
get => list[index];
set => list[index] = value;
}
반응형