2014-12-10 5 views
-1

IDisposableusing 블록을 사용하여 행복하지만 여분의 인스턴스화 코드 및 이름 지정 등을 피하기 위해 (new Obj()).Foo();을 작성하는 경우가 종종 있습니다.이 인스턴스는 함수 범위의 끝까지 메모리에 멈추거나 둘러싸는 괄호 바로 뒤에 처리됩니까? 나왔다 ...? 제가 누락 된 대안이 있습니까? 한 번 사용하고 버릴 구체적인 개체에 IDisposable을 구현하는 것과 동일합니까?C#에서는 (새 Obj()).() 괄호 범위가 종료 될 때 Obj를 처리합니까?

+1

Obj 클래스가 IDisposable을 구현합니까? 쓰레기 수거가 아니라 여기서 폐기 처분하는 거지? – hatchet

+0

많은 참고 문헌에서 설명했듯이 'IDisposable'을 구현하는 이유는 결정적 정리를 제공하기위한 것입니다. 명시 적으로'IDisposable.Dispose()'를 호출하지 않으면 결정 론적으로 발생하지 않으며, 결국 GC의 자비에 따라 최종자를 호출하게됩니다. 예 : [Dispose 메서드 구현하기] (http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx) –

+0

아니요, 이것을 사용하는 더 간결한 방법은'using (Obj o = new Obj()) o.Foo();' –

답변

2

IDisposable은 개체에 할당 된 메모리가 해제 될 때 관련이 없습니다. 두 경우 모두 가비지 콜렉터가 메모리를 해제하기로 결정하면 메모리가 해제됩니다.

IDisposable은 할당 된 리소스를 해제하기 위해 일부 작업을 실행해야하는 개체에 사용됩니다. 예를 들어 개체가 데이터베이스 연결을 열면 더 이상 필요하지 않으면 즉시 해제해야합니다. ,

은 그래서 괜찮아 USING 절을 폐기() 메서드를 호출하거나 사용하여

  • 즉시 당신이 원하는대로 리소스를 해제하는 방법 :

    그래서는 IDisposable 당신에게 한 가지를 제공합니다

    new Obj()).Foo(); 
    

    를 그리고 그렇지 해제해야하는 모든 리소스를 사용 않는 경우, obj가는 IDisposable을 구현하게하는 것은 의미가 없습니다 :해야 할 일. 객체가 IDisposable를 구현하는 경우

+0

Obj가 IDisposable을 구현하는 경우 처리를 무시해도 괜찮지 않을 수 있습니다. 리소스가 유한 한 경우 (종종 리소스가있는 경우) 개체가 완료되기 전에 리소스를 소모 할 수 있습니다. 나는 이것이 .Net의 이메일 클래스에서 일어나는 것을 보았다. IDisposable이 구현되면 개체를 명시 적으로 처리해야합니다. – hatchet

+0

네, 전적으로 동의합니다. 그러나 일부 프로그래밍 오류 때문에 Dispose 메서드가 호출되지 않는 경우 적어도 GC에서 수집 할 때 리소스가 해제됩니다. 의견을 주셔서 감사 드리며,이를 반영하기 위해 답변을 편집하겠습니다. – pol

+0

개체에 finalizer (C++ 소멸자 구문과 유사한 구문을 사용하는 메서드)가 없으면 GC가 실행될 때 GC가 관리되지 않는 리소스 또는 부족한 리소스를 자동으로 해제하지 않습니다. GC는'IDisposable'을 찾지 않으며 파이널 라이저를 찾습니다. 파이널 라이저가있는 경우, 파이널 라이 제이션을위한 객체를 표시하고 다음에 실행될 때 파이널 라이저를 호출합니다. 파이널 라이저는'Dispose()'를 호출해야하지만, 클래스의 소비자가 리소스를 명시 적으로 해제 할 수 없다는 것을 의미하는 'IDisposable'없이 파이널 라이저를 사용할 수도 있습니다. – Craig

2

, 그것은 (!도 및 내 시도는/마지막으로 구성)을 Dispose() 명시 적으로 자신의 코드에서 객체가 필수적거나 using 구문으로, 간단하지 않습니다 참조가 범위를 벗어납니다.

EDIT : 나는이 모든 것의 가장 중요한 측면을 설명하기 위해 많은 말을 사용하고있는 것처럼 느낍니다. 객체가 구현해야하는 유일한 이유는 IDisposable입니다. (CLR은 그들에 대해 알지 못함) 또는 부족합니다 (자원/비용/라이센스/등으로 인해). 따라서 객체가 IDisposable을 구현하는 경우 최대한 빨리 Dispose() YOURSELF를 호출해야합니다. CLR은 당신을 위해 그것을하지 않을 것입니다. 그리고 자신의 클래스에 IDisposable을 구현하면 파이널 라이저도 구현해야합니다.

단순히 범위에서 참조 가을을시키는 것은 하지 원인을 즉시 실행할 수있는 GC를 수행, 당신은 GC가 조만간 발생할 것이라는 것을 전혀 보장이 없습니다. 코드를 사용하여 GC를 명시 적으로 트리거 할 수는 있지만, 일반적으로 전체적인 성능을 손상시키는 데 도움이됩니다.

예를 들어 메모리 사용량이 많지 않은 경우 CLR은 GC를 실행하기 전에 오래 기다릴 수 있습니다. 자원에 대한 경합이나 제로가 존재하는 상황에서 실행하기위한 긴급한 필요는 없습니다. 실행 빈도가 너무 높으면 응용 프로그램의 성능에 부정적인 영향을 미칩니다.

GC는 Dispose()을 호출하지 않습니다. GC는 개체의 파이널 라이저가 있으면 파이널 라이저를 호출합니다. 파이널 라이저는 C++ 소멸자와 비슷한 구문을 사용하는 특별한 방법이지만 실제로는 소멸자가 아닙니다.

개체가 IDisposable을 구현하지만 종료자를 구현하지 않으면 GC는 해당 개체의 리소스를 절대로 릴리스하지 않습니다. 개체가 메모리 누수와 확인할 수없는 리소스 경합을 일으킬 수 있습니다.

코드에서 Dispose()을 호출하면 GC가 트리거되지 않습니다.

finalizer는 희소하고 값 비싼 리소스를 보유하는 클래스가 최종 사용자가 명시 적으로 해당 리소스를 해제하지 못한 경우에도 보내도록 보장하기 위해 시도하는 마지막 도랑 백업 메커니즘입니다.

IDisposable은 호출자가 부족한 리소스를 보유한 모든 클래스가 해당 리소스를 즉시 해제하도록 요청할 수 있도록 편리한 잘 알려진 인터페이스 계약으로 구현되는 실제적인 개념입니다.

표준 패턴은 finalizer가 Dispose() 메서드를 호출한다는 것입니다 (실제로는 일반적으로 Dispose(false)을 호출하며 의도적으로 그 세부 사항을 무시합니다). Dispose() 메서드는 부족한 리소스를 모두 해제 한 다음 GC.SuppressFinalize() 메서드를 호출하여 GC가 실행될 때 개체의 메모리를 더 빠르게 해제 할 수 있습니다.

이전에 시도한 "습득/릴리스 초기 획득"의미론이 여기에 적용됩니다.

GC가 finalizers를 사용하여 개체를 정리하는 데 여러 통과 또는 "세대"를 사용하는 방법을 읽어야합니다.

GC는 한 번에 일반 개체 (모든 리소스가 CLR에서 관리되는 개체)를 제거 할 수 있습니다. 객체에 범위 내 참조가 없으면 GC는 기본적으로 객체를 삭제할 수 있습니다.

개체에 파이널 라이저가있는 경우 (및 GC.SuppressFinalize()이 호출되지 않은 경우) GC는 개체를 해제하는 데 적어도 2 패스 또는 세대를 사용합니다. 1 세대에서는 완성 대상을 표시합니다. 2 세대 (GC가 다음에 실행될 때 발생 함)에서는 실제로 최종자를 호출하고, 그 시점에서 객체가 마침내 메모리를 해제 할 수 있습니다.

우리가 얘기하는 희소하고 값 비싼 리소스는 일반적으로 네트워크 소켓, 파일 핸들, 데이터베이스 또는 기타 서버 연결이 제한되거나 비싸거나 자원 집약적이거나 세 가지 모두 일 수 있습니다. Win32 윈도우 핸들, 파일 핸들, 네트워크 소켓 등과 같은 거의 모든 "관리되지 않는"(.NET CLR이 아닌) 리소스. 이러한 자원에는 결정 론적 정리가 필요합니다. 할 수있는 한 빨리 그 (것)들을 놓아 줄 필요가있다, 그러나 CLR는이 재료를 위로 청소하기 위하여 주변에 얻기의 감미로운 시간을 걸릴 것이다. 너 혼자해야 해.

그러나 이러한 유형의 부족한/비싼/"관리되지 않는"리소스를 사용하지 않는 클래스의 경우 IDisposable을 전혀 구현할 이유가 없습니다.