C#에서 Final/Disposure 방법 사용
C# 2008
저는 이것에 대해 잠시 동안 작업을 해왔는데, 아직도 코드에서 finalize 및 dispose 방법을 사용하는 것에 대해 혼란스럽습니다.제 질문은 다음과 같습니다.
관리되지 않는 리소스를 폐기하는 동안 최종 사용자만 필요하다는 것을 알고 있습니다.그러나 관리되지 않는 리소스를 호출하는 관리되는 리소스가 있는 경우에도 Finalizer를 구현해야 합니까?
되지 않는 간접적으로그나러관않리를직또간사로면개않지클발하를래스는하용으접적을 해야 합니다.
IDisposable해당 클래스의 클라이언트가 '문 사용'을 사용할 수 있도록 허용합니까?클래스의 클라이언트가 사용 명세서를 사용할 수 있도록 ID 일회용을 구현할 수 있습니까?
using(myClass objClass = new myClass()) { // Do stuff here }Finalize/Disposure 사용법을 보여주기 위해 아래의 간단한 코드를 개발했습니다.
public class NoGateway : IDisposable { private WebClient wc = null; public NoGateway() { wc = new WebClient(); wc.DownloadStringCompleted += wc_DownloadStringCompleted; } // Start the Async call to find if NoGateway is true or false public void NoGatewayStatus() { // Start the Async's download // Do other work here wc.DownloadStringAsync(new Uri(www.xxxx.xxx)); } private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) { // Do work here } // Dispose of the NoGateway object public void Dispose() { wc.DownloadStringCompleted -= wc_DownloadStringCompleted; wc.Dispose(); GC.SuppressFinalize(this); } }
소스 코드에 대한 질문:
여기서 저는 피니시저를 추가하지 않았으며, 일반적으로 피니시저는 GC에 의해 호출되고 피니시저는 Dispose를 호출할 것입니다.피니시저가 없어서 Dispose 메소드는 언제 불러요?그것을 불러야 하는 것은 수업의 고객입니까?
이 예제의 클래스는 No Gateway라고 하며 클라이언트는 다음과 같이 클래스를 사용하고 폐기할 수 있습니다.
using(NoGateway objNoGateway = new NoGateway()) { // Do stuff here }실행이 사용 중인 블록의 끝에 도달하면 Dispose 메서드가 자동으로 호출됩니까? 아니면 클라이언트가 Dispose 메서드를 수동으로 호출해야 합니까?
NoGateway objNoGateway = new NoGateway(); // Do stuff with object objNoGateway.Dispose(); // finished with it는 사용중다니입▁the를 사용하고 있습니다.
WebClient의 수업NoGatewayㅠㅠ 때문에. 왜냐하면WebClient는 을 합니다.IDisposable인터페이스, 이것은 다음을 의미합니까?WebClient관리되지 않는 리소스를 간접적으로 사용합니까?이것을 따르기 위한 어렵고 빠른 규칙이 있습니까?클래스가 관리되지 않는 리소스를 사용하는지 어떻게 알 수 있습니까?
권장되는 ID 일회용 패턴은 여기에 있습니다.ID를 사용하는 클래스를 프로그래밍할 때는 일반적으로 두 가지 패턴을 사용해야 합니다.
관리되지 않는 리소스를 사용하지 않는 봉인된 클래스를 구현할 때는 일반 인터페이스 구현과 마찬가지로 Dispose 방법을 구현하기만 하면 됩니다.
public sealed class A : IDisposable
{
public void Dispose()
{
// get rid of managed resources, call Dispose on member variables...
}
}
봉인되지 않은 클래스를 구현할 때 다음과 같이 수행합니다.
public class B : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
// get rid of unmanaged resources
}
// only if you use unmanaged resources directly in B
//~B()
//{
// Dispose(false);
//}
}
아직 최종 결정자를 발표하지 않았습니다.B삭제할 관리되지 않는 실제 리소스가 있는 경우에만 finalizer를 구현해야 합니다.은 CLR이 가능한 객체와 불가능한 객체를 합니다.SuppressFinalize이 호출됩니다.
그래서, 당신은 당신이 필요하지 않는 한 파이널라이저를 선언해서는 안 되지만, 당신은 당신의 클래스의 상속자들에게 당신을 부를 수 있는 훅을 줍니다.Dispose관리되지 않는 리소스를 직접 사용하는 경우에는 다음과 같이 직접 finalizer를 구현합니다.
public class C : B
{
private IntPtr m_Handle;
protected override void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
ReleaseHandle(m_Handle);
base.Dispose(disposing);
}
~C() {
Dispose(false);
}
}
되지 않는 직접 (관리되지 않는 리소스를 사용하는 경우)SafeHandle그리고 친구들은 자신의 결승전 진출자를 선언할 때 카운트하지 않습니다). 그러면 GC가 결승전 진출자를 나중에 억제하더라도 결승전 진출자를 다르게 처리하기 때문에 결승전 진출자를 구현하지 않습니다.또한 주의해야 할 것은, 비록B피니시저가 없어요, 여전히 호출합니다.SuppressFinalizeFinalizer를 구현하는 하위 클래스를 올바르게 처리합니다.
클래스가 ID 일회용 인터페이스를 구현하는 경우 클래스 사용을 마치면 제거해야 하는 관리되지 않는 리소스가 있음을 의미합니다.실제 리소스는 클래스 내에 캡슐화되므로 명시적으로 삭제할 필요가 없습니다.간단히 전화하기Dispose()을 는수로업을포다니장합또▁a로로 묶습니다.using(...) {}필요에 따라 관리되지 않는 리소스를 모두 제거합니다.
구현하기 위한 IDisposable이해하기 어렵습니다.저는 이것이 더 낫다고 믿습니다.
public class BetterDisposableClass : IDisposable {
public void Dispose() {
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
protected virtual void CleanUpManagedResources() {
// ...
}
protected virtual void CleanUpNativeResources() {
// ...
}
~BetterDisposableClass() {
CleanUpNativeResources();
}
}
관리되지 않는 리소스에 대해 항상 래퍼 클래스를 생성해야 하는 규칙을 사용하는 것이 더 좋은 해결 방법은 다음과 같습니다.
public class NativeDisposable : IDisposable {
public void Dispose() {
CleanUpNativeResource();
GC.SuppressFinalize(this);
}
protected virtual void CleanUpNativeResource() {
// ...
}
~NativeDisposable() {
CleanUpNativeResource();
}
}
및 그 파생물과 함께, 이러한 클래스는 매우 드물 것입니다.
상속이 있는 경우에도 관리되지 않는 리소스를 직접 처리하지 않는 일회용 클래스의 결과는 강력합니다. 즉, 더 이상 관리되지 않는 리소스에 대해 걱정할 필요가 없습니다.구현과 이해가 간단합니다.
public class ManagedDisposable : IDisposable {
public virtual void Dispose() {
// dispose of managed resources
}
}
ID 일회용 구현은 다음 패턴(IMHO)을 따라야 합니다.저는 몇몇 우수한 사람들의 정보를 바탕으로 이 패턴을 개발했습니다.NET "신들" 그.NET Framework 설계 지침(MSDN은 어떤 이유로든 이 지침을 따르지 않습니다!)..NET Framework 설계 가이드라인은 Cwalina(당시 CLR 설계자)와 Brad Abrams(당시 CLR 프로그램 관리자), Bill Wagner([Effective C#]) 및 [Mever Effective C#](다음을 참조하십시오. Amazon.com :
클래스에 관리되지 않는 리소스가 직접 포함되어 있지 않으면(상속되지 않는) Finalizer를 구현하지 마십시오.클래스에서 Finalizer를 구현한 후에는 호출되지 않더라도 추가 수집을 위해 사용할 수 있습니다.단일 스레드에서 실행되는 Finalization 큐에 자동으로 배치됩니다.그리고 아주 중요한 메모가 하나 있습니다...Finalizer 내에서 실행되는 모든 코드는 스레드 세이프 및 예외 세이프여야 합니다!그렇지 않으면 나쁜 일이 발생합니다...(예: 결정되지 않은 동작 및 예외의 경우 복구할 수 없는 치명적인 애플리케이션 충돌).
제가 작성한 패턴(및 코드 스니펫 작성)은 다음과 같습니다.
#region IDisposable implementation
//TODO remember to make this class inherit from IDisposable -> $className$ : IDisposable
// Default initialization for a bool is 'false'
private bool IsDisposed { get; set; }
/// <summary>
/// Implementation of Dispose according to .NET Framework Design Guidelines.
/// </summary>
/// <remarks>Do not make this method virtual.
/// A derived class should not be able to override this method.
/// </remarks>
public void Dispose()
{
Dispose( true );
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
// Always use SuppressFinalize() in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize( this );
}
/// <summary>
/// Overloaded Implementation of Dispose.
/// </summary>
/// <param name="isDisposing"></param>
/// <remarks>
/// <para><list type="bulleted">Dispose(bool isDisposing) executes in two distinct scenarios.
/// <item>If <paramref name="isDisposing"/> equals true, the method has been called directly
/// or indirectly by a user's code. Managed and unmanaged resources
/// can be disposed.</item>
/// <item>If <paramref name="isDisposing"/> equals false, the method has been called by the
/// runtime from inside the finalizer and you should not reference
/// other objects. Only unmanaged resources can be disposed.</item></list></para>
/// </remarks>
protected virtual void Dispose( bool isDisposing )
{
// TODO If you need thread safety, use a lock around these
// operations, as well as in your methods that use the resource.
try
{
if( !this.IsDisposed )
{
if( isDisposing )
{
// TODO Release all managed resources here
$end$
}
// TODO Release all unmanaged resources here
// TODO explicitly set root references to null to expressly tell the GarbageCollector
// that the resources have been disposed of and its ok to release the memory allocated for them.
}
}
finally
{
// explicitly call the base class Dispose implementation
base.Dispose( isDisposing );
this.IsDisposed = true;
}
}
//TODO Uncomment this code if this class will contain members which are UNmanaged
//
///// <summary>Finalizer for $className$</summary>
///// <remarks>This finalizer will run only if the Dispose method does not get called.
///// It gives your base class the opportunity to finalize.
///// DO NOT provide finalizers in types derived from this class.
///// All code executed within a Finalizer MUST be thread-safe!</remarks>
// ~$className$()
// {
// Dispose( false );
// }
#endregion IDisposable implementation
파생 클래스에서 사용할 수 있는 ID를 구현하기 위한 코드입니다.ID로부터의 상속을 파생 클래스 정의에서 명시적으로 나열할 필요는 없습니다.
public DerivedClass : BaseClass, IDisposable (remove the IDisposable because it is inherited from BaseClass)
protected override void Dispose( bool isDisposing )
{
try
{
if ( !this.IsDisposed )
{
if ( isDisposing )
{
// Release all managed resources here
}
}
}
finally
{
// explicitly call the base class Dispose implementation
base.Dispose( isDisposing );
}
}
저는 이 구현을 블로그 "폐기 패턴을 올바르게 구현하는 방법"에 게시했습니다.
저는 pm100에 동의합니다. (그리고 이것은 제 이전 게시물에서 명시적으로 말했어야 했습니다.
당신이 필요하지 않는 한 수업에서 ID를 사용할 수 없습니다.매우 구체적으로 말하면, ID가 필요하거나 구현되어야 하는 경우가 약 5번 있습니다.
클래스에는 ID를 구현하는 관리되는 리소스가 명시적으로 포함되어 있습니다(예: 상속을 통해 포함되지 않음). 클래스가 더 이상 사용되지 않으면 정리해야 합니다.예를 들어 클래스에 Stream, DbCommand, DataTable 등의 인스턴스가 포함되어 있는 경우.
클래스에는 Close() 메서드를 구현하는 관리되는 리소스가 명시적으로 포함되어 있습니다.IDdataReader, IDbConnection 등이러한 클래스 중 일부는 Close() 메서드뿐만 아니라 Dispose() 메서드를 사용하여 ID Disposable을 구현합니다.
클래스에 관리되지 않는 리소스(예: COM 개체, 포인터)가 명시적으로 포함되어 있습니다(예, 관리되는 C#에서 포인터를 사용할 수 있지만 '안전하지 않은' 블록으로 선언해야 합니다).관리되지 않는 리소스의 경우에도 시스템을 호출해야 합니다.런타임.Interop Services.보안관님RCW의 ReleaseComObject(). RCW는 이론적으로 관리되는 래퍼이지만 커버 아래에서 참조 카운팅이 진행 중입니다.
클래스가 강력한 참조를 사용하여 이벤트를 구독하는 경우.이벤트 등록을 취소하거나 이벤트에서 분리해야 합니다.등록 취소/분리를 시도하기 전에 항상 이러한 항목이 null이 아닌지 확인하십시오!
클래스에 위의 모든 조합이 포함되어 있습니다.
COM 개체로 작업하고 마샬을 사용해야 하는 것에 대한 권장 대안입니다.ReleaseComObject()는 시스템을 사용하는 것입니다.런타임.Interop Services.SafeHandle 클래스입니다.
BCL(Base Class Library Team)은 여기 http://blogs.msdn.com/bclteam/archive/2005/03/16/396900.aspx 에서 이에 대한 좋은 블로그 게시물을 제공합니다.
WCF를 사용하여 리소스를 정리하는 경우에는 거의 항상 '사용' 블록을 피해야 합니다.MSDN에는 왜 이것이 나쁜 생각인지에 대한 많은 블로그 게시물이 있습니다.여기에도 게시했습니다. WCF 프록시와 함께 'using()'을 사용하지 마십시오.
ID 대신 람다를 사용하는 것은 일회용입니다.
저는 이 모든 것을 사용하는 것에 대해 흥분해 본 적이 없습니다.일회용 아이디어입니다.문제는 발신자가 다음을 수행해야 한다는 것입니다.
- 일회용 ID를 사용해야 한다는 것을 알고 있습니다.
- '사용'을 잊지 말고 사용하세요.
제가 선호하는 새로운 방법은 공장 방식을 사용하고 대신 람다를 사용하는 것입니다.
SqlConnection(사용법으로 포장해야 하는 것)으로 무언가를 하고 싶다고 상상해 보십시오.고전적으로 당신은 할 것입니다.
using (Var conn = Factory.MakeConnection())
{
conn.Query(....);
}
뉴웨이
Factory.DoWithConnection((conn)=>
{
conn.Query(...);
}
첫 번째 경우에는 호출자가 구문 사용을 사용할 수 없었습니다.두 번째 경우에는 사용자가 선택할 수 없습니다.SqlConnection 개체를 만드는 메서드가 없으므로 호출자가 DoWithConnection을 호출해야 합니다.
DoWithConnection은 다음과 같습니다.
void DoWithConnection(Action<SqlConnection> action)
{
using (var conn = MakeConnection())
{
action(conn);
}
}
MakeConnection은 비공개입니다.
아무도 당신이 ID가 필요하지 않음에도 불구하고 ID를 일회용으로 구현해야 하는지에 대한 질문에 대답하지 않았습니다.
단답: 아니요
긴 답변:
이렇게 하면 클래스의 소비자가 '사용'을 사용할 수 있습니다.제가 묻고 싶은 질문은 - 왜 그들이 그것을 했을까요?대부분의 개발자들은 그들이 반드시 - 그리고 어떻게 그들이 알고 있는지 알지 못하는 한 '사용'을 사용하지 않을 것입니다.어느 하나
- 그것은 경험으로부터 그들을 제거합니다 (예를 들어 소켓 클래스).
- 그것이 문서화된.
- 그들은 신중하고 학급이 ID를 일회용으로 구현하는 것을 볼 수 있습니다.
따라서 ID Disposable을 구현함으로써 개발자(적어도 일부)에게 이 클래스가 릴리스되어야 하는 것을 마무리한다고 말합니다.그들은 '사용하기'를 사용할 것입니다. 하지만 사용할 수 없는 다른 경우도 있습니다. (객체의 범위가 로컬이 아닙니다.) 그리고 그들은 다른 경우에 개체의 수명에 대해 걱정하기 시작해야 할 것입니다. 저는 확실히 걱정할 것입니다.하지만 이것은 필요하지 않습니다.
사용자는 사용자가 사용할 수 있도록 ID를 구현하지만 사용자가 사용하도록 지시하지 않는 한 사용자는 사용을 사용하지 않습니다.
그러니까 하지 마
폐기 패턴:
public abstract class DisposableObject : IDisposable
{
public bool Disposed { get; private set;}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~DisposableObject()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (!Disposed)
{
if (disposing)
{
DisposeManagedResources();
}
DisposeUnmanagedResources();
Disposed = true;
}
}
protected virtual void DisposeManagedResources() { }
protected virtual void DisposeUnmanagedResources() { }
}
상속의 예:
public class A : DisposableObject
{
public Component components_a { get; set; }
private IntPtr handle_a;
protected override void DisposeManagedResources()
{
try
{
Console.WriteLine("A_DisposeManagedResources");
components_a.Dispose();
components_a = null;
}
finally
{
base.DisposeManagedResources();
}
}
protected override void DisposeUnmanagedResources()
{
try
{
Console.WriteLine("A_DisposeUnmanagedResources");
CloseHandle(handle_a);
handle_a = IntPtr.Zero;
}
finally
{
base.DisposeUnmanagedResources();
}
}
}
public class B : A
{
public Component components_b { get; set; }
private IntPtr handle_b;
protected override void DisposeManagedResources()
{
try
{
Console.WriteLine("B_DisposeManagedResources");
components_b.Dispose();
components_b = null;
}
finally
{
base.DisposeManagedResources();
}
}
protected override void DisposeUnmanagedResources()
{
try
{
Console.WriteLine("B_DisposeUnmanagedResources");
CloseHandle(handle_b);
handle_b = IntPtr.Zero;
}
finally
{
base.DisposeUnmanagedResources();
}
}
}
관리되지 않는 리소스를 사용하는 다른 관리 개체를 사용하는 경우 이러한 개체가 완료되었는지 확인하는 것은 사용자의 책임이 아닙니다.개체에 대해 삭제가 호출되면 해당 개체에 대해 삭제를 호출해야 합니다. 그러면 해당 개체가 중지됩니다.
만약 당신의 학급이 어떤 부족한 자원을 사용하지 않는다면, 저는 당신이 왜 당신의 학급이 ID를 사용하지 못하게 만드는지 이해할 수 없습니다.다음과 같은 경우에만 이 작업을 수행해야 합니다.
- 지금 당장은 아니지만 곧 개체에 리소스가 부족하게 될 것입니다(그리고 "우리는 아직 개발 중이며 완료되기 전에 완료될 것입니다"와 같이 "이것이 필요할 것 같습니다"와 같이).
- 부족한 리소스 사용
예, 코드를 사용하는 코드는 개체의 폐기 메서드를 호출해야 합니다.는 그고예, 당의객사를을 사용할 수 .
using당신이 보여준 것처럼.(또 2개?)Web Client가 관리되지 않는 리소스를 사용하거나 ID를 구현하는 다른 관리되는 리소스를 사용하지 않을 수 있습니다.하지만 정확한 이유는 중요하지 않습니다.중요한 것은 ID 일회용을 구현하기 때문에 Web Client가 다른 리소스를 전혀 사용하지 않는 것으로 판명되더라도 개체를 완료한 후 폐기함으로써 해당 지식에 따라 작업을 수행해야 합니다.
다음 두 가지 이유로 인해 다른 답변의 일부 측면이 약간 잘못되었습니다.
첫번째,
using(NoGateway objNoGateway = new NoGateway())
실제로는 다음과 같습니다.
try
{
NoGateway = new NoGateway();
}
finally
{
if(NoGateway != null)
{
NoGateway.Dispose();
}
}
Out Of Memory 예외가 없는 한 'new' 연산자가 'null'을 반환하면 안 되기 때문에 터무니없이 들릴 수 있습니다.그러나 다음과 같은 경우를 생각해 보십시오: 1.ID 일회용 리소스 또는 2를 반환하는 FactoryClass를 호출합니다.구현에 따라 ID에서 상속될 수도 있고 상속되지 않을 수도 있는 유형이 있다면 - 개발자들이 ID에서 상속받지 않고 Dispose() 메서드를 추가하는 많은 클라이언트에서 ID 일회용 패턴이 잘못 구현되는 것을 본 적이 있습니다(나쁜, 나쁜, 나쁜).또한 속성 또는 메서드에서 ID 일회용 리소스가 반환되는 경우(다시 불량, 불량, 불량 - ID 일회용 리소스를 '제공하지 않음')가 발생할 수 있습니다.
using(IDisposable objNoGateway = new NoGateway() as IDisposable)
{
if (NoGateway != null)
{
...
'as' 연산자가 null(또는 리소스를 반환하는 속성 또는 메서드)을 반환하고 'using' 블록의 코드가 'null'로부터 보호하는 경우, 'built-in' null 확인으로 인해 null 개체에서 Dispose(폐기)를 호출하려고 할 때 코드가 폭발하지 않습니다.
당신의 답변이 정확하지 않은 두 번째 이유는 다음과 같은 stmt 때문입니다.
GC가 당신의 객체를 파괴할 때 파이널라이저가 호출됩니다.
첫째, 최종화(GC 자체뿐만 아니라)는 비결정론적입니다.CLR은 최종 사용자를 호출할 시기를 결정합니다. 즉, 개발자/코드가 알지 못합니다.ID 일회용 패턴이 올바르게 구현되었는지 여부(위에 게시한 바와 같이) 및 GC.SuppressFinalize()가 호출되었지만 Finalizer는 호출되지 않습니다.이것이 패턴을 올바르게 구현해야 하는 큰 이유 중 하나입니다.논리 프로세서 수에 관계없이 관리되는 프로세스당 Finalizer 스레드가 하나뿐이므로 GC 호출을 잊어 Finalizer 스레드를 백업하거나 중단하여 성능을 쉽게 저하시킬 수 있습니다.Finalize()를 누릅니다.
저는 제 블로그에 Dispose Pattern의 올바른 구현을 게시했습니다.폐기 패턴을 올바르게 구현하는 방법
WebClient는 관리되는 유형이므로 Finalizer가 필요하지 않습니다.파이널라이저는 사용자가 NoGateway 클래스를 Dispose()하지 않고 GC에서 수집하지 않은 네이티브 유형을 정리해야 하는 경우에 필요합니다.이 경우 사용자가 Dispose()를 호출하지 않으면 포함된 WebClient는 NoGateway가 호출한 직후 GC에 의해 폐기됩니다.
간접적으로는 그렇습니다만, 걱정하지 않으셔도 됩니다.코드가 현재 상태로 올바르고 사용자가 쉽게 폐기()를 잊어버리는 것을 방지할 수 없습니다.
msdn의 패턴
public class BaseResource: IDisposable
{
private IntPtr handle;
private Component Components;
private bool disposed = false;
public BaseResource()
{
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
Components.Dispose();
}
CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}
~BaseResource()
{ Dispose(false);
}
public void DoSomething()
{
if(this.disposed)
{
throw new ObjectDisposedException();
}
}
}
public class MyResourceWrapper: BaseResource
{
private ManagedResource addedManaged;
private NativeResource addedNative;
private bool disposed = false;
public MyResourceWrapper()
{
}
protected override void Dispose(bool disposing)
{
if(!this.disposed)
{
try
{
if(disposing)
{
addedManaged.Dispose();
}
CloseHandle(addedNative);
this.disposed = true;
}
finally
{
base.Dispose(disposing);
}
}
}
}
using(NoGateway objNoGateway = new NoGateway())
와 동등합니다.
try
{
NoGateway = new NoGateway();
}
finally
{
NoGateway.Dispose();
}
GC가 객체를 파괴할 때 파이널라이저가 호출됩니다.이 시간은 메서드를 종료할 때와 완전히 다른 시간일 수 있습니다.사용 중인 블록을 떠난 후 즉시 Dispose of ID Dispose(ID 처분)가 호출됩니다.따라서 이 패턴은 일반적으로 더 이상 필요하지 않은 리소스를 즉시 사용하여 리소스를 해제하는 데 사용됩니다.
Finalizer/Destrator는 사용하지 않는 것이 좋습니다.
public ~MyClass() {
//dont use this
}
대부분, 이는 언제 호출될지 또는 호출될지 모르기 때문입니다.특히 직접 사용하거나 폐기하는 경우 폐기 방법이 훨씬 좋습니다.
사용하는 것이 좋습니다.사용하세요 :)
언급URL : https://stackoverflow.com/questions/898828/use-of-finalize-dispose-method-in-c-sharp
'programing' 카테고리의 다른 글
| ASP에서 Excel 파일을 생성하는 중입니다.그물 (0) | 2023.05.07 |
|---|---|
| Bash 스크립트에서 현재 디렉토리 변경 (0) | 2023.05.07 |
| 각도 2 검정:'input'의 알려진 속성이 아니므로 'ngModel'에 바인딩할 수 없습니다. (0) | 2023.05.07 |
| MDF 파일이란? (0) | 2023.05.07 |
| Python3에서 인덱스별로 dict_keys 요소 액세스 (0) | 2023.05.07 |