C# 프로그래밍

[C#] 익명 메소드와 람다식

같은편 2023. 2. 28. 17:30

2023.02.27 - [C# 프로그래밍] - [C#] 대리자(Delegate)

 

[C#] 대리자(Delegate)

C#에서 대리자는 콜백(Callback)을 구현하기 위해 사용됩니다. 콜백이란 어떤 일을 해줄 코드를 만들고, 이 코드가 실행할 이벤트 코드는 컴파일 시점이 아닌 프로그램이 실행 중인 시점에 부여하

onesside-world.tistory.com

이번 게시물을 이해하려면 무조건 전 게시물인 대리자에 대해 알고 있어야 합니다.

 

1. 익명 메소드

일단 예제부터 살펴보겠습니다.

delegate int Calculate(int x, int y);

class Program
{
    static void Main(string[] args)
    {
        Calculate calc
        calc = delegate(int x, int y) 
        { 
            return x + y; 
        };
        
        int result = calc(10, 20);
        Console.WriteLine(result); // 30 출력
    }
}

위의 코드에서 보시다시피 메소드가 있긴 한데 이름이 없습니다.

calc은 대리자 인스턴스고 dlelgate도 그냥 키워드 일 뿐 메소드인데 이름이 없는 이게 바로 익명 메소드입니다.

이런 불편할 것 같은 방식의 익명 메소드도 때때로 굉장히 유용하게 사용됩니다.

예를 들어 대리자가 참조할 메소드를 넘겨야 할 일이 생겼는데, 이 메소드가 두 번 다시 사용할 일이 없다고 판단되면

익명 메소드를 사용하면 좋습니다.

 

그러면 이번엔 전 게시물에 썼던 버블 정렬 프로그램을 익명 메소드로 바꿔보겠습니다.

using System;

namespace AnonymouseMethod
{
    delegate int Compare(int a, int b);

    class MainApp
    {
        static void BubbleSort(int[] DataSet, Compare Comparer)
        {
            int i = 0;
            int j = 0;
            int temp = 0;

            for (i = 0; i < DataSet.Length - 1; i++)
            {
                for (j = 0; j < DataSet.Length - (i + 1); j++)
                {
                    if (Comparer(DataSet[j], DataSet[j + 1]) > 0)
                    {
                        temp = DataSet[j + 1];
                        DataSet[j + 1] = DataSet[j];
                        DataSet[j] = temp;
                    }
                }
            }
        }

        static void Main(string[] args)
        {
            int[] array = { 3, 7, 4, 2, 10 };

            Console.WriteLine("Sorting ascending...");
            //메소드의 이름이 없습니다.
            BubbleSort(array, delegate(int a, int b)
                              {
                                if (a > b)
                                    return 1;
                                else if (a == b)
                                    return 0;
                                else
                                    return -1;
                              });

            for (int i = 0; i < array.Length; i++)
                Console.Write($"{array[i]} ");

            int[] array2 = { 7, 2, 8, 10, 11 };
            Console.WriteLine("\nSorting descending...");
            BubbleSort(array2, delegate(int a, int b)
                               {
                                 if (a < b)
                                     return 1;
                                 else if (a == b)
                                     return 0;
                                 else
                                     return -1;
                               });

            for (int i = 0; i < array2.Length; i++)
                Console.Write($"{array2[i]} ");

            Console.WriteLine();
        }
    }
}

2. 람다식

(추신. 람다식으로 만드는 익명 메소드는 무명 함수(Anonymous Function)이라는 이름으로 부르기도 함)

람다식으로 만드는 익명 메소드는 위의 대리자 부터 익명 메소드까지 이해했다면 아주 쉽습니다.

그냥 진짜 아래 코드를

BubbleSort(array, delegate(int a, int b)
                              {
                                if (a > b)
                                    return 1;
                                else if (a == b)
                                    return 0;
                                else
                                    return -1;
                              });

이렇게 바꾸면 됩니다.

BubbleSort(array, (a, b) => a.CompareTo(b));

진짜 너무 편해졌습니다.(CompareTo() 메소드는 찾아보시길 부탁드립니다. 설명이 샛길로 빠질 수 있어서;)

 

여기서! C# 컴파일러는 위 코드를 더 간결하게 만들 수 있도록 "형식 유추(Type Inference)"라는 기능을 제공합니다.

형식 유추를 사용하면 다음과 같이 람다식에서 매개 변수의 형식을 제거할 수 있습니다.

//컴파일러는 Compare 대리자의 선언 코드로부터 이 람다식이 만드는
//익명 메소드의 매개 변수의 형식을 유추해냅니다.
BubbleSort(array, (a, b) => a.CompareTo(b));

 

이제 이 글은 본 분들도 익명 메소드는 던져 버리고 람다식만 쓰게 될 겁니다.