2009-11-30 2 views
1

IDictionary 인스턴스 멤버를 통해 다른 클래스에 대한 참조를 보유하는 몇 가지 클래스가 있습니다.소멸자가 왜 불려 가고 있습니까?

과 같이 :

class A 
{ 
    private readonly Dictionary<int, B> _particles = new Dictionary<int, B>(); 
    public void CreateNewB(int someInt) 
    { 
    var b = new B(); 
    if (!_particles.ContainsKey(someInt) 
     _particles.Add(someInt, b); 
    } 
} 

그래서 이것은 설치하고, 나는이 사전에서 제거하지 마십시오,하지만 어떤 이유로, 클래스 B의 소멸자는 모든 이제 다음과 GC의 실행에 호출되는 이유는 모르겠다.

Dictionary 클래스가 새로운 참조를 추가하는 방법과 관련이있을 수 있습니까? FIXED

:

좋아, 나는 확실히 지금 GC와 deconstructors에 대한 많은 이해를 얻을 수 있습니다, 귀하의 답변에 대한 여러분 모두 감사합니다.

그러나 이미 및 결함이 비즈니스 로직을 통해 존재하지 않은 경우에만 문제가, 내가 someInt을 내 자신의 추가 하였다, someInt는 항상 1, 그래서 그것을 통해 처음 일을하고 deconstructors은하지 않았다 라는. 그러나 두 번째로 "b"인스턴스는 단순히 목록에 추가되지 않고 GC 실행에서 정리되었습니다.

도와 주신 모든 분들께 다시 한번 감사드립니다.

+0

동작을 재현하는 코드를 가장 작게 줄 수 있습니까? – jason

+0

"Dictionary 클래스가 새로운 참조를 추가하는 방법과 관련이 있습니까?" 아주있을 법하지 않습니다. 사전에는 사전 참조가 수집 될 때까지 키 또는 값이 수집되지 않도록하는 강력한 참조가 있습니다. – itowlson

+0

@Mark : 좋다, 안도의 한숨이다.설명하는 동작은 코드에 결함이 없으면 발생하지 않아야합니다. 우리가 "도울 수있어서 기쁘다." – jason

답변

0

답장을 보내 주셔서 감사합니다. 이제 GC와 deconstructors에 대해 많은 것을 알고 있습니다.

그러나 문제는 내 자신이었습니다. 이미 존재하지 않았고 결함이있는 비즈니스 로직을 통해 someInt를 추가하는 중이었습니다. someInt는 항상 1 이었으므로 처음으로 작동하고 deconstructors는 호출되지 않았습니다. 그러나 두 번째로 "b"인스턴스는 단순히 목록에 추가되지 않고 GC 실행에서 정리되었습니다.

나는 이것을 닫으려고 대답하고 있습니다 :)

3

클래스 B는 클래스 A에 대한 참조가

+0

나는 그가 "A"의 인스턴스에 대한 참조를 여전히 가지고 있다고 가정하는 것이 안전하다고 생각한다. (나는 결코이 사전에서 그들을 제거하지 않는다.) 나는이 사전을 의미한다고 가정한다. 'A'는 여전히 존재합니다). – jason

+0

이 정확한지, 클래스 A의 소멸자에 Console 문을 만들었습니다. 결코 호출되지 않습니다. – Mark

1

나는이 사전에서 제거하지 마십시오 죽은 경우 GC 수 있지만 어떤 이유로, 클래스 B의 소멸자가 호출되는

.NET의 소멸자는 C++ (관리되지 않음)의 소멸자와 동일하지 않습니다.
소멸자가 Finalize 메서드를 자동으로 호출합니다. 여기

destructor는 어떤 특성이다 :

  • 소멸자 구조체에서 정의 될 수 없다. 클래스와 함께 사용됩니다.
  • 클래스에는 하나의 소멸자 만있을 수 있습니다.
  • 소멸자는 상속되거나 과부하 될 수 없습니다.
  • 소멸자 이라고 할 수 없습니다. 그들은 이 자동으로 호출됩니다.
  • 소멸자는 한정자를 사용하거나 매개 변수를 사용하지 않습니다.

    1. 클래스 A는 쓰레기를 수집 :

그래서 귀하의 경우에는 무슨 일이 일어나고 있는지이 (2 단어)입니다.

  • 1 : _particles 필드의 결과로 GC-d를 얻습니다.
  • 2의 결과로 사전의 항목이 뿌리가되지 않게되었습니다 (가비지 수집 가능).
  • 3의 결과 : 사전 (클래스 B 인스턴스)의 항목은 GC-d입니다.
  • 는 사전 클래스는 새로운 참조를 추가하는 방법을 함께 할 수있는 뭔가를 할 수 있을까요?

    번호

    +0

    이 경우도 마찬가지라고 생각하여 클래스 A의 소멸자에 Console 문을 넣었습니다. 전혀 호출되지 않습니다. .. – Mark

    +0

    질문에 소멸자가 없습니다. 당신이 그렇게한다면 그것은 많이 바뀝니다. 따라서 모든 문제 코드를 제공하는 것이 좋습니다. –

    -2

    I 클래스 B에 내 돈을 내기 것이 다른 곳에서 생성된다. 콘솔 앱인 경우 B 생성자 및 종료 자에 결과를 출력합니다. 인스턴스 생성의 수를 기대 한대로하십시오.

    type k { 
    public k() { Console.WriteLine("Hi, I'm a new K!"); } 
    public ~k() { Console.WriteLine("I'm a dying K!"); } 
    } 
    

    그리고 간단한 코드 :

    0

    그래서 나는 다음과 같은 유형이

    Dictionary<int, k> ks = new Dictionary<int, k); 
    for(int i=0;i<10;i++) { ks.add(i, new k()); } 
    

    을 당신은 ~ K() 한 지점에서 callled되고 있음을 볼 수? 그게 무슨 일이야?

    1

    뭔가 잘못한 것처럼 들립니다. 관리되는 환경에서 이러한 객체를 유지하려고하지 않는 한 기본적으로 영원히 살 수있는 참조를 유지하면 메모리 누수가 발생합니다.

    여기서 기억해야 할 또 다른 점은 C#에서는 소멸자와 같은 것이 없다는 것입니다. 당신이 가지고있는 것은 finalizers입니다. 관리 코드에서 최종자를 작성해야하는 경우는 거의 없습니다. 이렇게해야하는 유일한 이유는 IDisposable을 유형의 finalizer에 포함되지 않은 관리되지 않는 리소스 을 래핑하도록 구현할 때입니다.

    예를 들어 많은 사람들이 IDisposable을 구현하고 데이터 액세스 계층의 일부로 SqlConnection을 래핑하는 형식을 만듭니다. 이렇게하면 블록을 사용하여 형식의 인스턴스를 래핑하고 만든 SqlConnections가 제대로 배치되는지 확인할 수 있습니다. 그러나이 유형은 이 아니며은 최종 데이터베이스 연결이 SqlConnection 클래스 자체의 마무리 자에 이미 적용되어 있기 때문에 최종자를 필요로합니다. 걱정하지 않아도되는 관리되지 않는 리소스 유형은 SqlConnection 유형뿐입니다. 그러나 완전히 새로운 데이터베이스 엔진을 구축하고 새로운 .Net 데이터 공급자를 구현하려는 경우 연결을 위해 finalizer를 구현해야합니다.

    +0

    좋은 물건 Joel. 파이널 라이저가 .NET에서 가장 이해하기 어려운 개념 중 하나 인 것처럼 보이는 것이 흥미 롭습니다. 하나 추가. – jason

    관련 문제