2011-07-05 7 views
2

다음과 같은 설정이 있다고 가정 해 보겠습니다.객체가 범위를 벗어날 때 이벤트 핸들러는 어떻게됩니까?

public class ClassA 
{ 
    public event EventHandler SomeEvent; 
} 

public class ClassB : IDisposable 
{ 
    public void SomeMethod(ClassA value) 
    { 
     value.SomeEvent += (s, e) => { DoSomething(); }; 
    } 

    void DoSomething() { } 

    void Dispose() { } 
} 

public static class Program 
{ 
    static void Main() 
    { 
     var a = new ClassA(); 

     using (var b = new ClassB()) 
     b.SomeMethod(a); 

     // POINT OF QUESTION!! 
    } 
} 

"POINT OF QUESTION"다음에 SomeEvent 이벤트가 발생하면 어떻게됩니까?

+0

이 C#, .NET인가요? 내가 가서 그 태그를 추가했다;) – IAbstract

답변

6

폐기 된 개체의 메서드를 호출합니다. 그래서 구독을 취소하는 것이 중요합니다. 심지어 메모리 누수가 발생할 수 있습니다.

+0

그냥 런타임 오류가 발생하지 않을까요? (Null 포인터 참조 또는 일부). – Hogan

+5

@Hogan Disposing은 가비지 수집과 같지 않습니다. 이 경우'b'는'a' 이벤트 (정확히 문제)에 여전히 참조가 있으므로 가비지 수집되지 않습니다. 'b'의 구현이 정확하다면'ObjectDisposedException'을 던질 것입니다. –

+0

@ 주케 - 펑크가 null을 가리키는 지 궁금합니다. 나는 이것이 일어날 수있는 방법이 없다고 생각합니다. – Hogan

0

ClassA 이벤트 수신을 거부하려면 Dispose() ClassB 메소드를 사용해야합니다. 가비지 수집되지 않는 클래스가 위험을 감수하면 잠재적으로 메모리 누수가 발생할 수 있습니다. 항상의 이벤트가 발생했습니다.

1

위 항목 중 아무 것도 이벤트 처리기를 언 후크합니다. ab이 동시에 범위를 벗어나기 때문에 안전 할 수 있습니다. ab을 모두 수집 할 수 있으므로 ab을 유지하지 않습니다.

using 문 다음에 ClassA.SomeEvent 이벤트를 발생 시키려면 b이 삭제 되었더라도 ClassB.DoSomething이 호출됩니다. 이 경우 이벤트 처리기를 명시 적으로 제거해야합니다.

다른 곳의 a에 대한 참조를 유지하려는 경우 ba으로 유지됩니다. 이벤트 처리기가 제거되지 않았으므로 다시 말합니다.

0

아무 것도 없습니다. 런타임은 Dispose 메소드에 대해 알지 못하고 statement를 사용하여 메모리 관리를 전혀하지 않고이 메소드를 호출한다.

가비지 콜렉션은 모든 메모리 관리에 대해,하지만 당신은 여전히 ​​자신을 생각해야하고 (예를 들어 Dispose에서 탈퇴하고, propertly) 수동으로 구현할 수 있도록 IDisposable (및 Finalizer)는 자원 관리에 관한 것입니다.

관련 문제