원문: Variable Scope in Lambda Expressions

람다(Lambdas)는 해당 람다 함수를 정의하는 메소드 내부의 스코프(scope)에 위치한 외부의 변수를 참조할 수 있다. 또한, 해당 람다식을 포함하는 형식의 스코프 내에서도 외부의 변수를 참조할 수 있다. 이런 식으로 변수들은 람다식 내부에서 캡처(captured)되며, 캡처되지 않은 변수들은 가비지 콜렉터(garbage collector)에 의해 수거된다. 외부의 변수는 반드시 람다식에 의해 사용되기 전에 초기화(assigned)되어야 한다. 다음은 이와 같은 규칙들에 대한 예시이다:

using System;

delegate bool D();
delegate bool D2(int a);

internal class Test
{
    private D del;
    private D2 del2;

    public void TestMethod(int input)
    {

        int j = 0;
        // 람다식으로 델리게이트(delegates)들을 초기화한다.  
        // 본 메서드에서는 총 2개의 외부 변수들에 접근한다는 사실에 주목하라.  
        // del은 이 메서드에서 호출될 것이다.  
        del = () => { j = 10; return j > input; };

        // del2는 TestMethod가 스코프를 벗어난 뒤에 호출될 것이다.  
        del2 = (x) => { return x == j; };

        // j의 값을 출력해 확인한다:
        // 출력: j = 0
        // 델리게이트는 아직 호출되지 않은 상태이다.  
        Console.WriteLine("j = {0}", j);
        bool boolResult = del();            // 델리게이트를 호출한다.

        // 출력: j = 10 b = True  
        Console.WriteLine("j = {0}. b = {1}", j, boolResult);
    }

    private static void Main(string[] args)
    {
        Test test = new Test();
        test.TestMethod(5);

        // del2는 여전히 TestMethod의 지역 변수 j의 복사값을
        // 가지고 있다는 사실을 증명한다.
        bool result = test.del2(10);

        // 출력: True  
        Console.WriteLine(result);

        Console.ReadKey();
    }
}

람다식에서의 변수 스코프에서는 다음과 같은 규칙들이 적용된다:

람다식에서의 변수 스코프 규칙들

  • 일단 캡처된(captured) 변수는 해당 변수를 참조하는 델리게이트가 가비지 컬렉터에 의해 수거될 순서가 오기 전까지는 가비지 컬렉터에 의해 수거되지 않는다.
  • 람다식 내부에서 생성한 변수들은 외부 메서드에서는 보이지 않는다(not visible).
  • 람다식은 in, ref, out과 같은 인자들을 해당 람다식이 위치한 메서드(enclosing method)에서 직접 캡처할 수 없다.
  • 람다식 내부에서의 반환문은 람다식이 위치한 메서드의 반환(return)을 발생시키지 않는다.
  • 람다식은 goto, break, continue와 같은 문장들을 통해 해당 블록 바깥으로 점프하는 경우 람다 함수 내부에 포함할 수 없다. 또한 점프 대상이 블록 내부에 있는데도 해당 점프문이 람다 함수 바깥에 있는 것 역시 오류(error)이다.
<끝>