2014-04-11 3 views
4

'a', 'b'및 'c'의 세 객체가 있다고 가정합니다. 'a'및 'c'는 정적으로 참조 된 서비스 단독 개체입니다. 'b'객체가 수명이 짧습니다. 즉, 정적 참조가 활성 상태를 유지하지 않습니다.한 개체의 메서드를 다른 개체로 전달하면 첫 번째 개체가 활성 상태를 유지합니까?

이제 'a'객체가 'b'객체의 인스턴스를 메소드 중 하나의 범위에 생성한다고 가정 해 보겠습니다.

public B() 
{ 
    C.ActionList.Add (SomeMethod); 
} 

void SomeMethod() 
{ 
... 
} 

이제 시간 객체 'B'가 살고 않습니다

B b = new B(); 

는 또한 클래스 B 이런 식으로 뭔가를 보이는 것으로 생각? 내 가정은 생성자를 호출 한 메서드의 범위를 벗어나서 살아 있다는 것입니다. 특히, 메서드가 객체 'c'의 'ActionList'에있는 한.

맞습니까? 그렇지 않다면 가비지 수집을하게됩니다. 'c'가 'ActionList'의 모든 메소드를 실행하면 어떻게됩니까?

보너스 질문 : 'B'에서의 메소드의 이름,하지만 익명의 생성자로 작성되지 않은 경우 무엇을 다음과 같이

public B() 
{ 
    C.ActionList.Add (() => { 
    ... 
    }); 
} 

답변

6

특히, 한 그 방법은 여전히 ​​그대로을위한 'c'의 'ActionList'.

네, 맞습니다. 인스턴스 메서드에 대한 대리자는 인스턴스 자체에 대한 "하드 참조"를 만들고이를 그대로 유지합니다. 두 번째 질문은 적합하지 않습니다.

이벤트 구독이 .NET에서 "메모리 누수"의 일반적인 원인 인 이유는 기술적으로 누출되지 않지만 이벤트 구독은 대리인을 기반으로하며 이와 동일한 동작을하므로 이벤트 구독이 유지됩니다. 인스턴스에의 참조

'b'의 메소드 이름이 지정되지 않았지만 익명으로 생성자의 람다로 작성되면 어떻게 될까요?

동일합니다. 람다가 해당 인스턴스의 상태를 사용하면 컴파일러가 해당 인스턴스를 참조하는 형식의 인스턴스 메서드로 바뀌고 참조를 유지합니다. (일부 람다 식은 닫힌 값, 인스턴스 등에 의존하지 않으면 정적 메서드로 변환 할 수 있습니다.이 경우 참조를 보유하지 않습니다.)

경우 ...의 내용에 따라 결정됩니다. 표현식이 () => { Console.WriteLine("Foo"); } 이외의 것이라면 인스턴스의 값을 닫을 필요가 없으며 문제의 인스턴스를 사용하지 않으므로 참조를 보유하지 않습니다. 그러나 () => { Console.WriteLine(this.Foo); }을 수행하는 경우 this을 참조하는 형식의 메서드를 만들고 클래스 인스턴스를 활성 상태로 유지합니다.

+0

+1 "이벤트 가입이 .NET 및 다른 언어에서"메모리 누수 "의 공통 소스 인 이유입니다. 자바 스크립트가 시작될 때 브라우저가 해제되지 않는 오래된 이벤트 핸들러로 인해 메모리가 누출됩니다. – samy