티스토리 뷰

개발일기/C#

람다식 기초

노럭맨 2018. 9. 5. 18:00

[개인적인 공부 포스팅입니다]



0. 혼자 주저리.


C#이란 언어를 이용한지 어언 2년 반 정도 지났다.

그럼에도 불구하고 나의 프로그래밍 실력은 그리 좋다고 체감하지 못했는데,

그 이유가 기초 실력을 쌓지 않고서 주구장창 필요한 것만 갖다 썼다는 것을 최근에 깨달았다.

다시 기초부터 공부하면서 하고 있는데, 어쨌든 그 와중에 가장 부족한 부분이 뭐인지 체크를 해보니

내가 가장 부족한 것은 람다식이었다.

실무에서 쓰이는 코드 중 내가 제대로 이해하지 못하고 그저 따라쓰기에 급급했던 것이 람다식이었는데 내가 한번도 제대로 공부하지 못해서 이해를 못한채로 계속 쓰고 있었던 것이다.

덕분에 gitHub같은 곳에서 코드를 봐도 이해를 잘못했던 것...

이에 제대로 한번 정리를 하려 한다.


1. C# Docs에서 볼 수 있는 대리자의 역사


다음과 같은 델리게이트 함수가 선언 중일 때,

delegate void TestDelegate(string s);


C# 1.0 스타일

TestDelegate testDelA = new TestDelegate(M); //M은 메서드이름임


개인적인 첨언 : 이해하기에는 가장 쉬운 스타일. M이라는 메서드를 델리게이트에 집어넣는다.


C# 2.0 스타일 TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };

개인적인 첨언 : 2.0으로 오면서 new 키워드가 아니라 바로 M메서드에 있던 내용을 익명 함수로 만들어 넣을 수 있게 되었다. 인스턴스하지 않아서 메모리를 아끼고.. 매개변수를 바로 집어넣을 수 있게 하는 변화였던 것으로 추측 중... (정확하지 않음)


C# 3.0 스타일 TestDelegate testDelC = (x) => { Console.WriteLine(x); };


개인적인 첨언 : 2.0보다 확연하게 코드의 양이 줄었다. =>라는 연산자를 통해서 익명함수에 매개변수를 전달하는 느낌이랄까... 파라미터가 없으면 소괄호에 아무것도 없이 ()만으로 되겠지. 이것때문에 이해가 바로 되지 않은 것 같다! 그리고 이 3.0 스타일을 람다식이라고 한다고 한다고 한다고 한다고 함.



2. 일단 무명 메서드에 대해서 공부합시당.


람다식 이전에 무명메서드가 있었고, 람다식에선 불가능하지만 무명메서드 기존버전에선 가능한 게 있기 때문에 이를 알고 있어야합니다.


무명메서드를 선언하면 좋은 점은!

 - 코딩 오버헤드가 줄어듭니다. ( https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/statements-expressions-operators/anonymous-methods )



선언되어있는 무명 메서드에 내용 추가하기!

testDelB += delegate (string x) { Console.WriteLine("나도끼워줘.."); };


그 외에는 docs에 좋은 예제가 있어서 첨부하는 것으로 마무리합니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Declare a delegate.
delegate void Printer(string s);
 
class TestClass
{
    static void Main()
    {
        // Instantiate the delegate type using an anonymous method.
        Printer p = delegate(string j)
        {
            System.Console.WriteLine(j);
        };
 
        // Results from the anonymous delegate call.
        p("The delegate using the anonymous method is called.");
 
        // The delegate instantiation using a named method "DoWork".
        p = DoWork;
 
        // Results from the old style delegate call.
        p("The delegate using the named method is called.");
    }
 
    // The method associated with the named delegate.
    static void DoWork(string k)
    {
        System.Console.WriteLine(k);
    }
}
/* Output:
    The delegate using the anonymous method is called.
    The delegate using the named method is called.
*/
cs



3. 람다식에 대해서 봅시다


(1) Expression Lambdas


일단 가장 기초적인 예제입니다. 중괄호가 없는 스타일로 이를 식 람다라고 합니다.(Expression Lambdas)


1
2
3
4
5
6
delegate int del(int i);  
static void Main(string[] args)  
{  
    del myDelegate = x => x * x;  
    int j = myDelegate(5); //j = 25  
}  
cs


보시다시피 myDelegate의 값에 들어가는 " x=>x*x" 부분이 다르다는 것을 볼 수 있는데요,

매개변수 x가 선언이 앞쪽에 되고 람다식 연산자인 =>가 들어간 이후에 익명 메서드의 내용을 집어넣게 됩니다.

※ 주의 : => 왼쪽 부분 매개변수 선언 부분에서 원래 괄호가 있어야 하는데 하나일 경우에는 생략할 수 있습니다. 매개변수 없을 때는 생략 안됨!! 빈괄호 넣어줘야됨. ex. (x, y) ,ex. () ,ex. x

※ 또한, 매개변수의 형식을 암시적으로 유추할 수 없을 때는 형식을 써주기도 합니다. ex.(int x, string y)


람다식이 쓰이는 곳은 LINQ에서 쿼리문으로 자주 쓰인다고 하네요.

* 첨언 : 사실... linq를 써본적이 없어서.... 사실 유니티 스크립트를 쓸 때 쿼리자체를 쓴적이 없습니다 그냥 데이터 for문에 넣고 if 했던거라... 제가 이렇게 대충대충했었습니다.. (반성) 그래서 코드도 길고 그랬던거군요.


(2) Statement Labdas


1
2
TestDelegate del = n => { string s = n + " World"
                          Console.WriteLine(s); };
cs


식 람다에서 중괄호를 쳐서 몇 줄이 되는 경우이다.

※. 문장은 2~3개가 보통임. 제한은 없으나 docs에서 은연중에 많이 넣지 말라고 하는 느낌!



(3) 비동기 람다


이건 그리 사용할 일이 많지 않을 것 같으니 넘어갈게요.


(4) 표준 쿼리 연산자와 람다식


자료구조의 종류에 상관없이 표준적으로 사용할 수 있는 Linq를 사용할 때 람다식으로 사용합니다.

그냥 다음 파트에서 제대로 더 알아보겠습니다.


4. 쿼리에 람다 식 사용하기!


참고로 말하면, 특히 Unity개발자 분들은... LINQ는 iOS에서 사용할 때 제한이 있기 때문에 모바일 개발을 하시는 분들은 적극적으로 사용하지 않기를 권합니다!

어쨌든 DB에서 사용하는 쿼리를 C#에서 사용할 수 있게 하는 게 LINQ입니다.

사실 짧게 설명할 수 있는 부분은 아니지만, 일단은 빠르게 보고 넘어가겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class IntroToLINQ
{        
    static void Main()
    {
        // The Three Parts of a LINQ Query:
        //  1. Data source.
        int[] numbers = new int[7] { 0123456 };
 
        // 2. Query creation.
        // numQuery is an IEnumerable<int>
        var numQuery =
            from num in numbers
            where (num % 2== 0
            select num;
 
        // 3. Query execution.
        foreach (int num in numQuery)
        {
            Console.Write("{0,1} ", num);
        }
    }
}
cs


윗 코드에서는 numquery변수 안에 linq 쿼리를 써서 값을 받고 있습니다.

DB를 공부하신 분이라면 익숙한 구문들일겁니다.

여기서의 자료구조는 배열인데 사실 어떤 자료구조든 간에 다 가능하다고 합니다.

암튼 여기서 람다식으로 표현하는 걸 한번 봐보죠.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SimpleLambda
{
    static void Main()
    {
 
        // Data source.
        int[] scores = { 907182937582 };
 
        // The call to Count forces iteration of the source
        int highScoreCount = scores.Where(n => n > 80).Count();
 
        Console.WriteLine("{0} scores are greater than 80", highScoreCount);
 
        // Outputs: 4 scores are greater than 80            
    }
}
cs


이 위에서는 Where 안에 람다 식을 써서 값을 특정하고 있습니다.

좀 더 짧게 하고 있네요.

음,

뭐 그렇답니다.

유니티로 iOS개발할 예정이면 IL2CPP로 LINQ를 하라는데

귀찮으니까 안하겠습니다...


빠이요

댓글
최근에 올라온 글
Total
Today
Yesterday
TAG
more
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31