4

電話するのは安全ではありませんか:

component.Dispose(); (nullをチェックした場合)

コードを次のように変更した場合、ファイナライザーから:

~MyResource()
{
    Dispose();
}
public void Dispose()
{
 // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            if(component != null) component.Dispose();   // !!! //

            CloseHandle(handle);
            handle = IntPtr.Zero;

            disposed = true;

        }
    GC.SuppressFinalize(this);
}

私はこれが機能することを知っています-しかしそれは安全ですか?

(以下の例から?)

コード例:(コードを変更する前)

http://msdn.microsoft.com/en-us/library/system.idisposable.dispose.aspx

using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
    // Pointer to an external unmanaged resource.
    private IntPtr handle;
    // Other managed resource this class uses.
    private Component component = new Component();
    // Track whether Dispose has been called.
    private bool disposed = false;

    // The class constructor.
    public MyResource(IntPtr handle)
    {
        this.handle = handle;
    }

    // Implement IDisposable.
    // Do not make this method virtual.
    // A derived class should not be able to override this method.
    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.
        GC.SuppressFinalize(this);
    }

    // Dispose(bool disposing) executes in two distinct scenarios.
    // If disposing equals true, the method has been called directly
    // or indirectly by a user's code. Managed and unmanaged resources
    // can be disposed.
    // If disposing 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.
    protected virtual void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called.
        if(!this.disposed)
        {
            // If disposing equals true, dispose all managed
            // and unmanaged resources.
            if(disposing)
            {
                // Dispose managed resources.
                component.Dispose();
            }

            // Call the appropriate methods to clean up
            // unmanaged resources here.
            // If disposing is false,
            // only the following code is executed.
            CloseHandle(handle);
            handle = IntPtr.Zero;

            // Note disposing has been done.
            disposed = true;

        }
    }

    // Use interop to call the method necessary
    // to clean up the unmanaged resource.
    [System.Runtime.InteropServices.DllImport("Kernel32")]
    private extern static Boolean CloseHandle(IntPtr handle);

    // Use C# destructor syntax for finalization code.
    // This destructor will run only if the Dispose method
    // does not get called.
    // It gives your base class the opportunity to finalize.
    // Do not provide destructors in types derived from this class.
    ~MyResource()
    {
        // Do not re-create Dispose clean-up code here.
        // Calling Dispose(false) is optimal in terms of
        // readability and maintainability.
        Dispose(false);
    }
  }
  public static void Main()
  {
    // Insert code here to create
    // and use the MyResource object.
  }
}
4

2 に答える 2

4

'component'の実装の詳細を知らずに安全に実行できるかどうかを判断するのは困難です。オブジェクトのファイナライズは順序付けられておらず、包含階層を尊重しないため、「コンポーネント」インスタンスはそうではないかもしれませんがnull、それを呼び出すまでにすでにファイナライズされている可能性がありますDispose。多くの場合Dispose、メソッドは、オブジェクトが完成する前に呼び出されることだけを期待しているため、そのタイプの安全性を念頭に置いて作成されていません。

ファイナライザーで他のオブジェクトに触れるなどの巧妙なことを検討する前に、このテーマに関するChrisBrummeのブログ投稿を読んでください。これは良い出発点です。

一般に、非常に特殊な状況を除いてDispose、含まれているオブジェクトのメソッドは、ファイナライズされたときに呼び出されても期待どおりに動作することがわかっている場合、あなたが尋ねたパターンは安全ではなく、推奨されるパターンに固執すると思いますパラメータを渡し、bool disposingそれがである場合にのみ管理対象オブジェクトに触れることtrue

于 2012-07-06T14:55:40.887 に答える
2

.netでは、他の状況と同じように、任意の手段でアクセスできるオブジェクトが存在することが保証され、そのようなオブジェクトのフィールドにアクセスでき、そのオブジェクトのプロパティアクセスまたはメソッド呼び出しをディスパッチできます。保証されていない唯一のことは、システムがFinalize参照されたオブジェクトに対してメソッドをすでに実行しているかどうかです。システムがすでにFinalizeオブジェクトで実行されている結果として、以前は何か有用なことを行っていたメソッドがそれを実行できなくなる可能性は十分にありますが、それはオブジェクトのFinalize()ルーチンの機能であり、関係はありません。ガベージコレクター自体。

于 2012-07-06T16:23:00.480 に答える