CodeGym /행동 /C# SELF /람다식 문법 ( =>)

람다식 문법 ( =>)

C# SELF
레벨 49 , 레슨 1
사용 가능

1. 소개

이미 알지 못했을 수도 있지만, 면접에서 자주 나오는 질문 중 하나는 “람다식에 대해 무엇을 아나요?” 입니다. 왜 물어볼까요? 람다는 C#에서 코드 양을 줄이고 표현력을 높여주는 매우 편리하고 '유행하는' 기능이기 때문입니다. 익명 메서드가 손글씨로 편지를 쓰는 것이라면, 람다식은 메신저로 메시지 보내는 것과 같습니다: 빠르고, 간결하고, 때로는 이모지도 보낼 수 있죠(거의 비슷하게).

람다식은 C# 3.0에서 도입되었고 이후 LINQ, 이벤트 핸들러, 쓰레드, 컬렉션, 심지어 .NET 기반 AI 라이브러리까지 널리 퍼졌습니다.

람다식은 코드 안에서 이름 없이 "제자리"에 메서드를 선언하는 방법으로, 아주 짧고 명확합니다. 기본 문법은 항상 다음과 같습니다:

(매개변수) => 표현식_또는_코드_블록

이 "화살표" => 는 흔히 “람다 연산자” 또는 “화살표” 라고 부릅니다.

작은 비유

레시피를 쓰는 방식을 떠올려 보세요: “사과를 한 개 가져와서, 자르고, 그릇에 넣는다”.
C#에서는 이렇게 됩니다:

(사과) => 자르다(사과)

2. 익명 메서드를 람다로 바꾸기

예를 들어, 델리게이트가 있습니다:

delegate int SquareDelegate(int x);

익명 메서드는 이렇게 쓸 수 있습니다:

SquareDelegate sq = delegate(int x) {
    return x * x;
};

이제 같은 걸 람다식으로 표현하면:

SquareDelegate sq = (int x) => { return x * x; };

하지만 C#은 타입을 추론할 수 있어서 더 축약할 수 있습니다:

SquareDelegate sq = x => x * x;

놀라운 간결함!

"일반" 메서드와 익명 함수 비교

방법 선언 위치 사용 가능 위치 단점
이름 있는 메서드 클래스 안 어디서나 이름 필요, 코드가 더 많음
익명 메서드 코드 안 델리게이트와 함께만 문법이 더 번거로움
람다식 코드 안 델리게이트와 함께 어디서나 가끔 타입이 불분명할 수 있음

3. 람다식 문법: 다양한 형태

매개변수

매개변수 없음:

Action hello = () => Console.WriteLine("안녕, 세계!");

매개변수 하나(괄호 생략 가능):

Func<int, int> inc = x => x + 1;

여러 매개변수(괄호 필요):

Func<int, int, int> sum = (a, b) => a + b;

람다 본문

한 표현식 — 중괄호와 return 없이:

x => x * x

코드 블록 — 중괄호 필요, return 필요:

(x, y) =>
{
    int z = x + y;
    return z * z;
}

매개변수 타입

대부분의 경우 타입을 적을 필요가 없습니다 — 컴파일러가 알아냅니다. 하지만 원하면 명시할 수 있습니다:

(x, y) => x + y      // 컴파일러가 타입을 추론.
(int x, int y) => x + y  // 명시 가능.

4. 주의점과 좀 더 현실적인 예

컬렉션과 함께 사용하기

우리의 학습용 미니 앱(예: 사용자 목록)을 기억하세요? 예를 들어 숫자 배열이 있습니다:

int[] numbers = { 1, 2, 3, 4, 5 };

짝수만 선택하고 싶다면:

var evenNumbers = numbers.Where(n => n % 2 == 0);

여기서 Where 는 LINQ 확장 메서드이고, 조건은 우리의 람다 필터입니다.

메서드로 전달하기

예를 들어, 델리게이트 타입 메서드가 있다고 합시다:

public delegate bool Filter(int number);

public static int[] FilterNumbers(int[] data, Filter predicate)
{
    var result = new List<int>();
    foreach (var n in data)
        if (predicate(n))
            result.Add(n);
    return result.ToArray();
}

이제 람다식을 전달합니다:

int[] evens = FilterNumbers(numbers, n => n % 2 == 0);

이벤트 핸들러로서의 람다

button.Click += (sender, args) => Console.WriteLine("버튼이 눌렸습니다!");

5. 표준 제네릭 델리게이트와 람다식

람다를 Func<>, Action<>, Predicate<> 없이 상상하기 어렵습니다. 이들은 특별한 델리게이트 타입입니다:

  • Action — 값을 반환하지 않습니다.
  • Func — 값을 반환합니다.
  • Predicatebool 을 반환하며, 보통 필터링에 사용됩니다.

Action 예제:

Action<string> log = message => Console.WriteLine(message);

log("이건 람다를 통한 메시지입니다!");

Func 예제:

Func<int, int, int> multiply = (a, b) => a * b;
int product = multiply(3, 5); // 15

Predicate 예제:

Predicate<int> isNegative = n => n < 0;

bool test = isNegative(-7); // true

6. 여러 표현식을 가진 람다: 블록이 필요한 경우

람다가 여러 작업을 수행해야 하면 중괄호와 명시적인 return 을 사용하세요:

Func<int, int, string> describeSum = (a, b) =>
{
    int sum = a + b;
    return $"합계: {sum}";
};

return 이 없으면 컴파일러가 불평합니다(하지만 왜인지 정확히 설명해주진 않고, 단순히 "모든 경로가 값을 반환하지 않습니다" 라고 할 때가 많습니다).

7. void 반환: Action

람다가 아무것도 반환하지 않을 때는 Action 을 사용하세요:

Action greet = () => Console.WriteLine("웃으세요 — 코드가 컴파일됩니다!");

람다는 원하는 만큼 많은 문장을 포함할 수 있습니다:

Action<int> printSquare = x =>
{
    int sq = x * x;
    Console.WriteLine($"숫자 {x} 의 제곱은 {sq} 입니다");
};

8. 제한과 흔한 실수

람다를 자유롭게 쓰고 싶어도 컴파일러가 항상 허용하지는 않습니다.

외부에서 캡처한 이름과 같은 이름의 변수를 선언할 수 없습니다.

시그니처가 델리게이트와 일치하지 않으면 에러가 발생합니다.

델리게이트가 값을 요구하면 값을 반환해야 합니다.

복잡한 람다에서는 중괄호를 잊지 마세요. 한 표현식인 경우 중괄호와 return 없이, 여러 문장이면 중괄호와 return 을 사용합니다.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION