10/18 람다식

정수현·2024년 10월 19일

C#

목록 보기
5/10
post-thumbnail

람다식(Ramda Expression)

  • 익명 함수(이름이 없는 메서드)를 작성하는 간결한 방법

  • 람다식을 사용하기 위해선 delegation이 필요하지만 delegation 함수는 사용하지 않아도 된다.

  • delegation : 특정 함수를 어딘가에 보관하여 보관된 함수를 호출하는 역할

  • 형식 ( ) =? { };

  • 예시
    (int a, int b) => { return a + b; }
    (int a, int b) => { a + b; }
    (a, b) => a + b;
    ⇒ 대체로 ③의 형태로 사용한다.


목차

¹ 람다식 선언 형식과 예

² 코드로서의 람다식

³ FUNC와 ACTION으로 더 간편하게 무명 함수 만들기



람다식 선언 형식과 예

delegate int Calculate(int a, int b);

static int add(int n1, int n2) 
{ 
    return n1 + n2; 
}

static void Main(string [] args)
{
    Calculate calc1 = add; //add메서드를 호출한다.
    Console.WriteLine("calc1 : {0}", calc1(10, 20));

    Calculate calc2 = (int a, int b) => a + b;
    Console.WriteLine("calc2 : {0}", calc2(10, 20));
}
  • 실행 결과 ✔
    calc1 : 30
    calc2 : 30

문장 형식의 람다식

  • 실행할 코드를 중괄호로 묶어 여러 문장을 포함할 수 있다.

  • 단일 표현식이 아닌 여러 동작을 수행해야 할 때 유용하다.

delegate void DoSomething();
static void Main(string [] args)
{
    DoSomething Dolt = () => 
    {
        Console.WriteLine("출력1");
        Console.WriteLine("출력2");
    };
    Dolt();
}
  • 실행 결과 ✔
    출력1
    출력2



코드로서의 람다식

익명 메서드를 람다식으로 변환 ①

static void ThreadFunc(object obj)
{
    Console.WriteLine("이름이 있는 메서드");
}

static void Main(string [] args)
{
    //1. 이름이 있는 메서드
    Therad thread1 = new Thread(ThreadFunc);
    thread1.Start();
    
    //2. 이름이 없는 메서드
    Thread thread2 = new Thread(
        delegate (object obj)
        {
            Console.WriteLine("이름이 없는 메서드");
        });
    thread2.Start();
    
    //3. 람다식을 이용한 메서드
    Thread thread3 = new Thread(
        (obj) => 
        {
            Console.WriteLine("람다식을 이용한 메서드");
        });
    thread3.Start();
}
  • 실행 결과 ✔
    이름이 있는 메서드
    이름이 없는 메서드
    람다식을 이용한 메서드

  • 이름이 없는 메서드를 사용할 땐 delegation 함수를 작성한다.

  • 람다식을 이용할 땐 delegation은 작성하되, delegation 함수는 작성하지 않아도 된다. (바로 람다식으로 표현한다.)

익명 메서드를 람다식으로 변환 ②

delegate int ? MyDivide(int a, int b);

static void Main(string [] args)
{
    MyDivide myDivide = (a, b) =>
    {
        if (b == 0) return null;
        return a / b;
    };
    
    Console.WriteLine("10 / 2 == {0}", myDivide(10, 2));
    COnsole.WriteLine("10 / 0 == {0}", myDivide(10, 0));
}
  • 실행 결과 ✔
    10 / 2 == 5
    10 / 0 ==

return문과 중괄호를 생략해도 된다.

delegate int MyAdd(int a, int b);

static void Main(string [] args)
{
    MyAdd myAdd = (a, b) => a + b;
    Console.WriteLine("10 + 2 == {0}", myAdd(10, 2));
}
  • 위 코드는 MyDivide myDivide = (a, b) => a / b;로 바꾸어 쓸 수 있다. (조건문이 없을 때)



Func와 Action으로 더 간편하게 무명 함수 만들기

  • 위의 방식에서는 하나의 익명 메소드를 만들기 위해 매번 delegate를 따로 선언해줘야 하는 불편함이 있다.

  • 이를 해결하기 위해서는 두 가지의 방식이 있다.
    Func delegate : 반환 값이 있다.
    Action delegate : 반환 값이 없다.

  • 즉, 반환 값이 있는 무명 함수를 쓰고 싶을 땐 Func 방식을 사용하고, 반환 값이 없는 무명 함수를 사용하고 싶을 땐 Action 방식을 사용한다.

① Func 사용 예
반환 형식이 있다.

static void Main(string [] args)
{
    //1. 입력매개변수 : 0개 / 반환 타입 : int 
    Func<int> func1 = () => 10;
    Console.WriteLine("func1() : {0}", func1());
    
    //2. 입력매개변수 : 1개, int형 / 반환 타입 : int
    Func <int, int> func2 = (x) => x * 2;
    Console.WriteLine("func2(4) : {0}", func2(4));
    
    //3. 입력매개변수 : 2개, int형 / 반환 타입 : double
    Func<double, double, double> func3 = (x, y) => x / y;
    Console.WriteLine("func3(22, 7) : {0}", func3(22, 7));
}
  • 실행 결과 ✔
    func1() : 10
    func2(4) : 8
    fun3(22, 7) : 3.14285714285714

  • Func 키워드의 꺽쇠 안에 ⑴ 입력 매개 변수의 타입을 그 개수에 맞게 적은 다음 ⑵ 반환할 타입(1개)을 마지막에 적는다.

② Action 사용 예
반환 형식이 없다.

static void Main(string [] args)
{
    //반환 타입 : 없음 / 입력매개변수 : 2개, double형
    Action<double, double> action = (x, y) =>
    {
        double pi = x / y;
        Console.WriteLine("Action<T1, T2>({0}, {1}) : {2}", x, y, pi);
    }
    action(22.0, 7.0);
}
  • 실행 결과 ✔
    Action<T1, T2>(22, 7) : 3.14285714285714

  • Action 키워드의 꺽쇠 안에 입력 매개 변수의 타입을 그 개수만큼 적는다.

연습
다양한 조건으로 검색이 가능한 메서드를 정의하고자 한다.

  • 검색을 다양하게 하기 위해서는 호출되는 시점에 필터링 조건을 걸어주면 된다.
private static List<int> FilterOfInts(int[] source, Func<int, bool> filter)
{
    List<int> result = new List<int>();
    foreach (int i int source)
    {
        if (filter(i)) result.Add(i);
    }
    
    return result;
}
  • int 배열에서 여러 조건으로 필터링 할 수 있는 메서드

  • 해당 값이 조건이 맞는지 확인해서 bool 형식을 반환하는 코드가 필요하므로 Func 방식을 사용하여 메서드를 정의하였다.

static void Main(string [] args)
{
    int[] source = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  
    // ---------------------- 홀수 필터 ----------------------
    List<int> oddNumbers = FilterOfInts(source, (i => (i & 1) == 1));
    //source 배열의 숫자가 홀수면 i(해당 숫자)를 oddNumbers 리스트에 추가
   
    Console.WriteLine("----- 홀수 필터 -----");
    foreach(var i in oddNumbers)
    {
        Console.Write(i+" "); //oddNumbers 리스트 요소들 출력
    }
  
    // ---------------------- 짝수 필터 ----------------------
    List<int> evenNumbers = FilterOfInts(source, (i => (i & 1) == 0));
    //source 배열의 숫자가 짝수면 i(해당 숫자)를 evenNumbers 리스트에 추가
   
    Console.WriteLine("\n----- 짝수 필터 -----");
    foreach(var i in evenNumbers)
    {
        Console.Write(i+" "); //evenNumbers 리스트 요소들 출력
    }
}
  • 실행 결과 ✔
    ----- 홀수 필터 -----
    1 3 5 7 9
    ----- 짝수 필터 -----
    2 4 6 8 10

  • (i => (i & 1) == 1)
    i & 1 : 비트 연산자 &를 사용하여 i의 가장 오른쪽 비트인 1을 비교한다.

  • 비트 연산은 i가 홀수일 경우 1을 반환하고, 짝수일 경우 0을 반환한다.

비교
delegation 활용과 Func 방식의 비교

delegate string Concatenate(string [] str);

static void Exam1()
{
    Console.WriteLine("[ 코드로서의 람다식(delegate) ]");
    
    string[] stringArr = { "aaa", "bbb", "ccc", "ddd" };
    
    Concatenate concatenate = (arr) => 
    {
        string result = "";
        foreach(string s in arr)
        {
            result += s;
        }
        return result;
    };
    Console.WriteLine(concatenate(stringArr);
}

static void Exma2()
{
    Console.WriteLine("[ Func 방식의 람다식 ]");
    
    string[] stringArr = { "aaa", "bbb", "ccc", "ddd" };
    
    Func<string[], string> concatenate = (arr) => 
    {
        string result = "";
        foreach(string s in arr)
        {
            result += s;
        }
        return result;
    }
    Console.WriteLine(concatenate(stringArr);
 }
  • 실행 결과 ✔
    [ 코드로서의 람다식(delegate) ]
    aaabbbcccddd
    [ Func 방식의 람다식 ]
    aaabbbcccddd

  • Exam1()
    : 함수 밖에 delegate을 생성하여 람다식을 작성하였다. 문자열 배열을 입력 받아 문자열 형태로 반환하고 있다.

  • Exam2()
    : 마찬가지로 Func 방식을 사용하여 문자열 배열을 입력 받아 문자열 형태로 반환하고 있다.

0개의 댓글