[C# 3.0] 람다

eunjin lee·2022년 10월 3일
0

C# 9.0 프로그래밍

목록 보기
32/50

람다 식은 익명 메서드의 간편 표기 용도로 사용된다.


1. 람다 메서드와 익명 메서드

💡 샘플 코드

Thread thread1 = new Thread(delegate (object obj) { Console.WriteLine("Delegate Anonymous Method Called."); });
Thread thread2 = new Thread((obj) => { Console.WriteLine("Lambda Anonymous Method Called."); });
  • 컴파일러는 Thread 타입의 생성자가 "void(object obj)" 형식의 델리게이트 인자를 받는다는 것을 알고 있으므로, 개발자가 람다식을 사용하여 delegate 예약어를 생략하고 인자의 타입을 명시하지 않아도 이를 익명 메서드와 완전히 동일하게 컴파일한다.

💡 샘플 코드

delegate int MyCalc(int a, int b);
static void Main(string[] args)
{
  MyCalc myPlus = (x, y) => x + y;
  Console.WriteLine(myPlus(4,10));

  MyCalc myMinus = (x, y) => x - y;
  Console.WriteLine(myMinus(5,10));

  MyCalc myDivide = (x, y) => {
                  				if (y == 0) { return 0; }
                  				return x / y; };

  Console.WriteLine(myDivide(50,0));
}
  • 약식의 경우 return문을 생략할 수 있고, 식이라는 특성으로 인해 중괄호가 허용되지 않는다. (세미콜론을 이용해 여러 줄의 코드를 넣을 수 없다.)

2. 람다 메서드와 전용 델리게이트

public delegate void Action();
→ 반환값이 없음.
public delegate TResult Func<out TResult>();
→ T 형식의 반환값이 있음.

💡 샘플 코드

        static void Main(string[] args)
        {
            Action printBlankAction = () => { Console.WriteLine("N/A"); };
            Action<string> printTxtAction = (txt) => { Console.WriteLine(txt); };
            Action<int, int> printPlusActoin = (a, b) => { Console.WriteLine(a + b); };
            printBlankAction();
            printTxtAction("hello");
            printPlusActoin(4, 10);

            Func<string> getBlankAction = () => "N/A";
            Func<string, int> getLengthAction = (txt) => txt.Length;
            Func<int, int, bool> checkPlusAction = (x, y) => { if (x + y > 0) { return true; } return false; };

            Console.WriteLine(getBlankAction());
            Console.WriteLine(getLengthAction("hello"));
            Console.WriteLine(checkPlusAction(-5,3));
        }

✅결과

N/A
hello
14
N/A
5
False
  • 람다 메서드는 일회성 코드에서 사용되는데, 일회성을 위해 델리게이트를 일일이 정의해야하는 것은 불편하다. 때문에 MS는 자주 사용되는 델리게이트 형식을 제네릭으로 일반화하여 BCL에 포함시켰다.
  • MS는 인자를 16개까지 받을 수 있는 Action과 Func를 미리 정의하여 제공한다.

3. 람다 메서드와 컬렉션

List<T>에 정의된 ForEach
public void ForEach(Action<T> action);
Array에 정의된 ForEach
public static void ForEach<T>(T[] array, Action<T> action)

💡 샘플 코드

List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
            
list.ForEach((element) => { Console.WriteLine(element); });
Array.ForEach(list.ToArray(), (element) => { Console.WriteLine(element * 2); });
  • ForEach 메서드는 Action를 델리게이트 인자로 받아 컬렉션의 모든 요소를 열람하면서 Action의 인자로 요소를 전달한다.

  • 요소0 열람 → 요소0에 대한 Action 수행 → 요소1 열람 → 요소1에대한 Action 수행 → 요소2 열람 → 요소2에 대한 Action 수행...


Enumerable 타입의 확장 메서드(using System.Linq;)
public static int Count(this IEnumerable source, Func<TSource, bool> predicate)
public static IEnumerable Where(this IEnumerable source, Func<TSource, bool> predicate)

💡 샘플 코드

List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
          
Console.WriteLine(list.Count((element) => element % 2==0));
Console.WriteLine(list.Where((element) => (element % 2 == 0)).ToList().Count()); 
  • 요소를 순회하면서 Func<T,bool> 델리게이트 수행하여 true인 것을 더한다.

public List FindAll(Predicate match)
public delegate bool Predicate(T obj);
T타입의 인자를 받아 bool을 반환하는 델리게이트를 통해, true인 경우에만 List의 형태로 반환함.

public static IEnumerable Where(this IEnumerable source, Func<T, bool> predicate)
T타입의 인자를 받아 bool을 반환하는 델리게이트를 통해, true인 경우에만 IEnumerable의 형태로 반환함.

  • FindAll은 메서드 실행이 완료되는 순간 컬렉션의 모든 요소를 대상으로 실행되어 조건을 만족하는 목록을 반환한다.
  • Where은 열거자를 통해 요소를 순회했을 때에야 비로소 람다 메서드가 하나씩 실행된다. → 지연된 평가(lazy evaluation)
  • 지연된 평가는 실제로 데이터가 필요한 순간에만 코드가 cpu에 의해 실행되는 장점이 있다.

public static IEnumerable Select<TSource, TResult>(this IEnumerable source, Func<TSource, TResult> selector)

💡 샘플 코드

List<int> intList = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
intList.ForEach(x => { Console.WriteLine(x/10); });

List<double> dbList = intList.Select(x => (double)x).ToList();
dbList.ForEach(x => { Console.WriteLine(x/10); });
  • Select문을 통해 형 변환을 할 수 있다.

💡 샘플 코드

List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };

var personList = list.Select(x => new Person { age = x, name = Guid.NewGuid().ToString() });
Array.ForEach(personList.ToArray(), x => { Console.WriteLine(x.name); });
  • Select문을 통해 객체를 생성하여 반환하는 것도 가능하다.

0개의 댓글