2010-06-18 6 views
3

는 I는 C#에서 메소드를 정의 할 때 I가 알고있는 것에 따라서,이 방법에서의 로컬 변수는,이 방법 [GC가 원할 때]의 블록을 실행 마치고 메모리인라인 코드는 실행 완료 후 메모리에 [작성한 메서드]를 유지합니까?

을 방출하지만 있다면 될 메서드에서 인라인 콜백을 수행하면 이러한 로컬 변수도 메모리에서 해제됩니까?

다음 예제에서 [x] 변수는 메서드 실행을 마친 후에도 값을 유지하며 콜백에 있지만 메시지에 [x] 값이 표시됩니다 !!

private void MyMethod() 
    { 
     int x = 1; 
     System.Timers.Timer t = new System.Timers.Timer(1000); 
     t.Elapsed += (sender, e) => MessageBox.Show((x++).ToString()); ; 
     t.Start(); 
    } 

답변

6

변수 x은 람다 함수와 관련된 폐쇄에서 캡처됩니다. 즉, x의 값은 MyMethod의 제외와 연관된 스택에 있지만 힙 (람다 함수에서 참조 된 객체에 있음)에 저장되어 있음을 의미합니다. 당신이 볼 수 있듯이

class $$MyMethod$$Closure { 
    public int x; 
    void Function(object sender, EventArgs e) { 
    MessageBox.Show((x++).ToString()); 
    } 
} 

private void MyMethod() { 
    var $$closure = new $$MyMethod$$Closure(); 
    $$closure.x = 1; 
    System.Timers.Timer t = new System.Timers.Timer(1000); 
    t.Elapsed += $$closure.LambdaFunction; 
    t.Start(); 
} 

x 변수가 이제 힙 할당 된 개체 (라는 폐쇄)에 저장됩니다

다음 예제 쇼 (약) C# 컴파일러는 코드를 변환하는 방법. 타이머가 메서드를 호출 할 수있는 한 (그리고 x에 액세스 할 수있는 한) 개체가 살아 있지만 타이머를 제거하면 클로저가 가비지 수집됩니다.

컴파일러 만 이 람다 함수에서 실제로 사용되는 로컬 변수를 캡처한다는 점에 유의할 가치가 있습니다 (따라서 메서드에 큰 데이터가있는 경우 실수로 필요 이상으로 오래 유지되지 않습니다) .

관련 문제