관리되지 않는 리소스를 "소유"하는 클래스는 무엇입니까(그리고 IDisposable을 구현하는 클래스는 무엇입니까)?
-
11-12-2019 - |
문제
나는 일하고있다 OSS 프로젝트 대중화시키려고 미디어정보 라이브러리 .NET에서 사용하기가 더 쉽지만 이 질문은 일반화 가능합니다.
파생 클래스인 경우 디 항상 객체를 인스턴스화합니다. 영형 기본 클래스를 호출할 때 DB의 생성자입니다.DB는 생성자에게 전송된 값으로 값을 설정하지만 값 자체는 다음에서 선언됩니다. DB의 기본 클래스 비:
- 누가 "소유"합니까? 영형 (아래 코드의 mediaInfo라고도 함)?
- .NET 애플리케이션의 경우 다음 중 IDisposable을 구현해야 하는 것은 무엇입니까?메모: 영형 관리되지 않거나 최소한 관리되지 않는 라이브러리를 둘러싸는 관리되는 객체의 인스턴스화이지만 "미디어정보.닫기();".이것이 "관리되지 않음"으로 간주되는지 확실하지 않습니다.
명확히 하기 위해 실제 코드를 사용해 보겠습니다.
디 ~에서 얻다 DB:
// MediaFile is "D"
public sealed class MediaFile : GeneralStream
{
public MediaFile(string filePath)
: base(new MediaInfo(), 0) {
// mediaInfo is "O"
mediaInfo.Open(filePath);
}
}
DB 상속된 항목을 설정합니다. 영형, 로부터 나오다 비:
// GeneralStream is "DB"
public abstract class GeneralStream : StreamBaseClass
{
public GeneralStream(MediaInfo mediaInfo, int id) {
this.mediaInfo = mediaInfo; // declared in StreamBaseClass
// ...
}
}
비 선언하다 영형:
// StreamBaseClass is "B"
public abstract class StreamBaseClass
{
protected MediaInfo mediaInfo; // "O" is declared
// ...
}
해결책
리소스에 대한 참조를 보유하는 개체가 이를 소유합니다.
StreamBaseClass
참조가 있습니다 mediaInfo
그리고 구현해야 IDisposable
.참고자료와 Dispose
메소드는 파생 클래스에 의해 자동으로 상속됩니다.
다른 팁
클래스 C가 IDisposable을 구현하는
클래스 D가 기본 자원 N을 소유 한 다음 D가 IDisposable (n)을 idisable해야하며 도 도 릴리스하기 위해 폐기 할 수있는 최종 소멸자가 있습니다.
이 패턴을 따르면 IDisposable이있는 경우 완료되면 항상 () 항상 객체 트리 아래로 모든 것을 삭제합니다.그러나 누군가가 당신을 잊어 버린 경우 (읽기 : 동료, 사용자의 라이브러리 사용자 등)은 기본 자원이 d 's finalizer에 의해 정리되므로 객체가 누출되지 않습니다.
책임 IDisposable
그 물건에 속한다. 창조하다 달리 명시적인 합의가 없는 경우.반대 계약은 일반적으로 리소스 작성자가 소비자의 수명을 전혀 모르는 경우에 사용됩니다.나는 많은 경우에 생성자나 팩토리 메소드가 전달된 객체의 마지막 소비자가 될 수 있는 것을 생성할 때 다음을 제안하고 싶습니다. IDisposable
, 해당 메소드는 호출에 대한 책임을 수락해야 하는지 여부를 나타내는 매개변수를 수락해야 합니다. Dispose
, 그렇지 않으면 null이 아닌 경우 소비자에게 더 이상 객체가 필요하지 않을 때 호출되는 콜백 대리자를 수락합니다.개체 작성자가 소비자보다 오래 지속되는 경우 null을 전달할 수 있습니다.객체가 전달된 후 작성자가 객체를 더 이상 사용할 수 없는 경우 객체의 Dispose
방법.작성자가 소비자보다 오래 지속될지 여부를 모르는 경우 개체가 여전히 필요한지 확인하는 메서드를 전달하고 호출할 수 있습니다. Dispose
그렇지 않다면.
귀하의 특정 사례와 관련하여 IDisposable
연결된 생성자 호출 내에는 리소스 누수에 대한 방법이 있습니다(연결된 생성자 호출을 try-finally 블록으로 래핑할 방법이 없기 때문입니다).어떻게든 안전하게 처리하려면(예:연결된 생성자 대신 팩토리 메소드를 사용하거나 [threadstatic]
hack), 객체 생성자(파생 클래스)가 소비자(기본 클래스)의 수명을 알 것이므로 소유권과 정리 책임은 객체 생성자에게 있어야 한다고 제안하고 싶습니다.