C#/C# 기본

[C#] 람다식

로파이 2021. 10. 15. 17:27

람다식

함수형 프로그래밍의 근간이 되는 람다 계산법에서 사용하는 식을 말한다.

C#에서 표현하는 람다식은 매개변수_목록 => 식 으로 표현된다.

 

- 예시

delegate int Function(int a, int b);

static void Main(string[] args)
{
	Function func = (int a, int b) => a + b;
}

컴파일러는 람다의 매개 변수의 타입을 지정하지 않아도 타입 유추를 통해 가능하다면 람다 함수를 생성할 수 있다.

Function func = (a, b) => a + b;

단일 실행문장이 아닌 여러 세미 콜론을 사용하는 문의 경우 중괄호를 이용하여 그 안에 실행하는 문장을 표현한다.

 

Function func = (a, b) => 
 {
	int c = a + b;	
	int d = a * b;
	return d / c;
};

 

Func과 Action 대리자 타입

Func 대리자는 반환 타입이 있는 함수를 명명할 수 있는 타입이다.

public delegate TResult Func<out TResult>();
public delegate TResult Func<in T, out TResult>(T arg);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 arg1, T2 arg2, T3 arg3);

타입 정의를 보면 타입 매개변수의 마지막 값은 항상 반환 형식이다.

Func<float, float, float, float> Length = (float a, float b, float c) =>
{
	return MathF.Sqrt(a * a + b * b + c * c);
};

float len = Length(5.0f, 3.0f, 4.0f);

Action 대리자는 반환 타입이 없는 함수를 명명할 수 있는 타입이다.

public delegate void Action<>()
public delegate void Action<in T>(T arg)
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2)
public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3)
Action<string> PrintMessage = (string msg) => Console.WriteLine($"{msg}");

표현식 트리 (Expression Tree)

계산식과 같은 표현 식을 트리 형태로 구성하고 런타임에 해당 식을 컴파일하여 실행할 수 있는 기능이다.

ex) x + 1 표현식 : + 연산자 부모에  "x" 파라미터 자식과 1 이라는 상수를 두고 있는 표현식 트리라고 할 수 있다.

모든 표현식 개체는 System.Linq.Expressions.Expressio 개체를 상속하며 연산이나 파라미터, 상수를 표현하기 위해 파생 클래스를 생성하여 사용한다.

Expression.XXX()는 구체저인 표현식 노드를 생성하는 팩토리 메서드 방식으로 제공한다.

 

- x + 1를 표현하는 방법

Expression const1 = Expression.Constant(1);
Expression param1 = Expression.Parameter(typeof(int), "x");

Expression exp = Expression.Add(const1, param1);

 

표현식의 컴파일과 실행

최종 표현식이 되는 트리의 부모는 컴파일까지 해야 실행할 수 있는 의미를 지닌다. 해당 표현식은 람다식으로 만들어 람다식을 컴파일하는 구조이다.

람다식 또한 Expression의 파생 클래스로 타입을 Func<> 혹은 Action<>으로 지칭하여 생성한다.

Expression.Lambda()라는 생성 메서드를 활용해서 표현식과 매개변수를 생성 매개변수로 전달하면 람다식을 만들 수 있다.

    // 람다식으로 전환
    // 표현식과 매개변수가 필요
    Expression<Func<int, int>> lambda1 = Expression<Func<int, int>>.Lambda<Func<int, int>>
    (exp, // 표현식
    new ParameterExpression[] { (ParameterExpression)param1 } // 매개변수 인자
    );

컴파일은 해당 람다식 객체의 Compile()를 호출하며 람다식의 타입으로 지정했던 대리자 형식의 인스턴스를 얻을 수 있다. 대리자 인스턴스를 사용하여 해당 표현식을 실행한다.

Func<int, int> compiledExp = lambda1.Compile();
 
Console.WriteLine(compiledExp(3));

 

Expression-Bodied Member 식으로 이루어지는 멤버

C#에서 람다식의 => 표현을 멤버의 메서드, 프로퍼티에 사용할 수 있다.

 

메서드에서 사용

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);
}

기본 메서드는 위와 같이 해당 메서드를 호출할 때 실행하는 함수를 지칭할 수 있다.

세미콜론을 둘 이상 포함해야하는 실행문은 지칭할 수 없다.

 

프로퍼티에서 사용

읽기 전용 프로퍼티와 인덱서는 다음과 같이 작성하며 get을 생략할 수 있다.

        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;  }

 

'C# > C# 기본' 카테고리의 다른 글

[C#] 리플렉션과 애트리뷰트  (0) 2021.10.19
[C#] LINQ  (0) 2021.10.18
[C#] 대리자와 이벤트  (0) 2021.10.15
[C#] Generic 프로그래밍 / 예외 처리  (0) 2021.10.12
[C#] 배열 / 컬렉션 / 인덱서  (0) 2021.10.11