본문 바로가기

Programming Language/C#

C# 기본 문법 – 대리자 편 2편. 무명 메서드와 람다식

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

C# 기본 문법 – 대리자 편
2편. 무명 메서드와 람다식

- by Tapitolife


지난번에는 대리자에 대한 기본적인 내용을 보았다면,
이번에는 여기에서 확장된 무명 메서드와 람다식에 대해 보겠습니다.

- 무명 메서드(Anonymous Methos) : 정식 메서드를 만들긴 좀……
단순 메시지 출력처럼 코드의 길이가 1~2줄 정도로 너무 짧은 경우……
C언어라면 매크로 함수나 인라인 함수를 쓰겠지만 C#에는 그런 기능이 없으니 애매하죠.
아니면 그렇게 자주 쓸 일이 없는 코드를 작성하는데 굳이 메서드를 만들어 줘야 하는가?

이런 고민에서 나온 것이 무명 메서드(Anonymous Method)
다른 말로 익명 메서드, 익명 대리자 등등으로도 불리죠.
말 그대로 메서드는 메서드인데 이름이 없습니다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace
CsTest
{
     class Program
    {
        delegate int DelegateMethod(int a, int b);

        static void Main(params string[] args)
        {
            DelegateMethod method = null;
            ConsoleKeyInfo c;
            bool menu = true;
             int ia = 0, ib = 0;

            while (true)
            {
                while (menu)
                {
                    Console.WriteLine("A. 덧셈");
                    Console.WriteLine("B. 뺄셈");
                    Console.WriteLine("C. 곱셈");
                    Console.WriteLine("D. 나눗셈");
                    Console.WriteLine("E. 나머지");
                    Console.WriteLine("Q. 끝");
                    Console.Write("어느 거임? >> ");

                    c = Console.ReadKey(false);

                    Console.Write('\n');

                     switch (c.KeyChar)
                    {
                        case 'A':
                         case 'a':
                            method = delegate(int a, int b) { return a + b; };
                            menu = false;
                            break;
                        case 'B':
                        case 'b':
                            method = delegate(int a, int b) { return a - b; };
                            menu = false;
                            break;
                        case 'C':
                        case 'c':
                            method = delegate(int a, int b) { return a * b; };
                            menu = false;
                            break;
                        case 'D':
                        case 'd':
                            method = delegate(int a, int b) { return a / b; };
                            menu = false;
                            break;
                        case 'E':
                        case 'e':
                            method = delegate(int a, int b) { return a % b; };
                            menu = false;
                            break;
                        case 'Q':
                        case 'q':
                            return;
                        default:
                            Console.WriteLine("뭥미? 다시 입력하셈요~");
                            break;
                        }
                }

                Console.Write("첫 번째 수를 입력하세요. >> ");
                ia = int.Parse(Console.ReadLine());
                Console.Write('\n');

                Console.Write("두 번째 수를 입력하세요. >> ");
                ib = int.Parse(Console.ReadLine());
                Console.Write('\n');

                Console.WriteLine("(a = {0})와 (b = {1})의 연산 결과는 {2}입니다.", ia, ib, method(ia, ib));
                menu = true;

                Console.Write('\n');
                Console.Write('\n');
            }
        }
    }
}

 

실행 결과는 다음과 같습니다.

 

여기서 주목해야 할 부분은 여기입니다.

switch (c.KeyChar)
{
    case 'A':
    case 'a':
        method = delegate(int a, int b) { return a + b; };
        menu = false;
        break;
    case 'B':
    case 'b':
        method = delegate(int a, int b) { return a - b; };
        menu = false;
        break;
    case 'C':
    case 'c':
        method = delegate(int a, int b) { return a * b; };
        menu = false;
        break;
    case 'D':
    case 'd':
        method = delegate(int a, int b) { return a / b; };
        menu = false;
        break;
    case 'E':
    case 'e':
        method = delegate(int a, int b) { return a % b; };
        menu = false;
        break;
    case 'Q':
    case 'q':
        return;
    default:
        Console.WriteLine("뭥미? 다시 입력하셈요~");
        break;
}

 

사용자의 입력에 따라서 method가 갖는 함수가 달라집니다.
그런데 그 함수가 클래스 상에 존재하는 함수는 아닙니다.
하나의 메서드 안에 delegate(int a, int b)로 시작해서 중괄호 안에
마치 또 하나의 함수처럼 코드 블록을 가진 것이 바로 무명 메서드입니다.

이전 버전의 C#에서는 return a + b; 이 한 줄을 위해 별도의 메서드를 따로 만들어야 했지만
C# 2.0부터는 메서드 내에서 자체적으로 해결이 가능해졌습니다.

이런 짓을 할 때 이점은 뭘까요? 그 이후를 보면 알 수 있습니다.

Console.WriteLine("(a = {0})와 (b = {1})의 연산 결과는 {2}입니다.", ia, ib, method(ia, ib));

아주 편리하죠. 이전에서 method에다 곱셈 함수를 넣든,
덧셈 함수를 넣든 이 줄에서는 method()를 간단히 호출만 하면 됩니다.

그런데 여기에서 또 한번 C#이 진화하게 됩니다.

 

- 람다 식(Lambda Expression) : 무명 메서드도 귀찮다! 더 간단하게!!
무명 메서드가 "메서드 안에 또 다른 메서드"와 같은 꼴이라면,
람다식은 무명 메서드를 더욱 더 슬림하게 한 것입니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CsTest
{
    class Program
    {
        delegate int DelegateMethod(int a, int b);

        static void Main(params string[] args)
        {
            DelegateMethod method = null;
            ConsoleKeyInfo c;
            bool menu = true;
            int ia = 0, ib = 0;

            while (true)
            {
                while (menu)
                {
                    Console.WriteLine("A. 덧셈");
                    Console.WriteLine("B. 뺄셈");
                    Console.WriteLine("C. 곱셈");
                    Console.WriteLine("D. 나눗셈");
                    Console.WriteLine("E. 나머지");
                    Console.WriteLine("Q. 끝");
                    Console.Write("어느 거임? >> ");

                    c = Console.ReadKey(false);

                    Console.Write('\n');

                    switch (c.KeyChar)
                    {
                        case 'A':
                        case 'a':
                            method = (a, b) => (a + b);
                            menu = false;
                            break;
                        case 'B':
                        case 'b':
                            method = (a, b) => (a - b);
                            menu = false;
                            break;
                        case 'C':
                        case 'c':
                            method = (a, b) => (a * b);
                            menu = false;
                            break;
                        case 'D':
                        case 'd':
                            method = (a, b) => (a / b);
                            menu = false;
                            break;
                        case 'E':
                        case 'e':
                            method = (a, b) => (a % b);
                            menu = false;
                            break;
                        case 'Q':
                        case 'q':
                            return;
                        default:
                            Console.WriteLine("뭥미? 다시 입력하셈요~");
                            break;
                    }
                }

                Console.Write("첫 번째 수를 입력하세요. >> ");
                ia = int.Parse(Console.ReadLine());
                Console.Write('\n');

                Console.Write("두 번째 수를 입력하세요. >> ");
                ib = int.Parse(Console.ReadLine());
                Console.Write('\n');

                Console.WriteLine("(a = {0})와 (b = {1})의 연산 결과는 {2}입니다.", ia, ib, method(ia, ib));
                menu = true;

                Console.Write('\n');
                Console.Write('\n');
            }
        }
    }
}

 

실행 결과는 이렇습니다. 위와 동일하죠.

 

여기서 주목할 것은 이 부분이죠~

case 'A':
case 'a':
    method = (a, b) => (a + b);
    menu = false;
break;

 

(a, b) => (a + b); 라고 된 부분이 바로 람다식입니다.
람다식의 기본 형식은 2가지입니다.

1. (매개변수) => {함수 본문;}

2. (매개변수) => 반환 식;

(a, b) => (a + b);를 다르게 표현하면 (a, b) => {return a + b;}와 같습니다.
무명 메서드와 다른 점은 일단 앞에 delegate라는 키워드도 없죠.
또한 매개변수의 형식을 굳이 명시할 필요도 없습니다. 이미 delegate 선언 때 다 했으니까요.
물론 (int a, int b) => (a + b);를 해도 되지만, 형식을 생략하고 암시적으로 (a, b) => (a + b);를 해도 됩니다.
정리하자면 람다식을 쓰면 무명 메서드를 쓸 때보다 불필요한 키워드나
중복되는 내용들을 생략할 수 있다는 이점이 있죠.

C# 버전에 따른 대리자의 변천은 이렇습니다.

C# 버전

C# 1.0

C# 2.0

C# 3.0

주요 특징

대리자(Delegate)

무명 메서드 지원

람다식 지원

구문 예

private int calc_add(int a, int b)
{
return a + b;
}
delegate int Func(int a, int b);
private void use()
{
Func func = calc_add;
int t = func(100, 100);
}

delegate int Func(int a, int b);
private void use()
{
Func func =
delegate(int a, int b)
{
return a + b;
}
int t = func(100, 100);
}

delegate int Func(int a, int b);
private void use()
{
Func func = (a, b) => (a + b);
int t = func(100, 100);
}

변화 양상

1. 코드의 분량 절감 (10줄 → 8줄 → 6줄)

2. 가독성 향상 (표현이 간결해짐)

 

이렇게 해서 대리자의 내용은 모두 끝났습니다. 읽어주셔서 감사합니다.