简体   繁体   English

在派生 class 中实现 IDisposable

[英]Implement IDisposable in derived class

If I have interface (example from apress book) which implementsIDisposable like this如果我有像这样实现IDisposable的接口(apress 书中的示例)

public interface IArchitectRepository : IDisposable
{
    IEnumerable<Architect> GetArchitects();
    Architect GetAchitectDetails(int id);
    void Create(Achitect a);
    void Update(Achitect a);
    void Delete(int id);
    void Save();
}

how would I implement Dispose method in derived class?我将如何在派生的 class 中实现 Dispose 方法?

In book the it's left as NotImplementedException .在书中,它被保留为NotImplementedException

There is no reason why you would implement the Dispose pattern any differently than normal. 没有理由要以不同于常规的方式实现Dispose模式。

See Implementing a Dispose Method 请参见实现处置方法

Unlike most interfaces which imply obligations on the part of an implementing class, the only obligation of a class which implements IDisposable is to regard a call to Dispose as adequate notice that an instance is going to be abandoned. 与大多数接口暗示实现类的义务不同,实现IDisposable的类的唯一义务是将对Dispose的调用视为充分注意实例即将被放弃的通知。 The real obligations imparted by IDisposable fall upon instance owners: if a type implements IDisposable , each instance should have one owner who is obligated to ensure that its Dispose method will gets called before it's abandoned; IDisposable赋予实例所有者的真正义务:如果一个类型实现IDisposable ,则每个实例应有一个所有者,该所有者有义务确保在放弃其Dispose方法之前将其调用; the owner may do this either by calling Dispose itself, or passing ownership to a new owner who would then assume the obligation. 所有者可以通过调用Dispose自己,或将所有权转让给新的所有者来承担责任。

Note that the owner of an IDisposable instance doesn't care what Dispose does provided that the instance may be safely abandoned after it returns. 请注意, IDisposable实例的所有者并不关心Dispose所做的事情,只要实例返回后可以安全地将其丢弃。 If some particular object can be safely abandoned before Dispose is called, there's no need for the Dispose method to do anything. 如果可以在调用Dispose之前安全地放弃某些特定对象,则不需要Dispose方法执行任何操作。 It should not throw a NotImplementedException or NotSupportedException , since it should be no able to doing everything it needs to do (ie nothing). 应该抛出一个NotImplementedExceptionNotSupportedException ,因为它应该是没有能够做需要做的(即没有)的一切。

You should look at MSDN for the complete example: http://msdn.microsoft.com/en-us/library/system.idisposable.aspx 您应该查看MSDN中的完整示例: http : //msdn.microsoft.com/zh-cn/library/system.idisposable.aspx

The minimum would be: 最小值为:

public class ArchitectRepository : IArchitectRepository
{
    // implement all the IArchitectRepository methods

    public void Dispose()
    {
        // assuming your repository has a connection property
        if (this.Connection != null)
            this.Connection.Close();
        // do the same for all other disposable objects your repository has created.
    }
}

Whiting the concrete implementation you can overwrite as follows 细化具体的实现,您可以如下覆盖

        public bool IsDisposed { get; set; }

        public bool IsLockedForDisposing { get; set; }


        /// <summary>
        /// Dispose the Loaded Context
        /// </summary>
        /// 
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    // Disposing of managed code
                    context.Dispose();
                    // GC.Collect(context);
                }
                this.disposed = true;
            }
        }

        public void Dispose()
        {
            if (!IsLockedForDisposing)
            {
                IsDisposed = true;
                Dispose(true);
                GC.SuppressFinalize(this);
            }
        }

I have some example code posted here (and included below): How do you properly implement the IDisposable pattern?我在这里发布了一些示例代码(包括在下面): How do you properly implement the IDisposable pattern?

Microsoft has slightly more in-depth details here: Implement a Dispose method微软在这里有更深入的细节: 实现一个 Dispose 方法

#region IDisposable base-class implementation
 
//TODO remember to make this class inherit from IDisposable -> MyDisposableClass : IDisposable
 
/// <summary>
/// Gets or sets a value indicating whether this instance is disposed.
/// </summary>
/// <value>
///  <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
/// </value>
/// <remarks>Default initialization for a bool is 'false'</remarks>
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"><c>true</c> to release both managed and unmanaged resources; 
/// <c>false</c> to release only unmanaged resources.</param>
/// <remarks>
/// <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 <c>false</c>, 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>
/// </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)
        {
            // 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.
            if (isDisposing)
            {
                // Release all managed resources here
                // Need to unregister/detach yourself from the events. Always make sure
                // the object is not null first before trying to unregister/detach them!
                // Failure to unregister can be a BIG source of memory leaks
                if (someDisposableObjectWithAnEventHandler != null)
                {                 
                    someDisposableObjectWithAnEventHandler.SomeEvent -= someDelegate;
                    someDisposableObjectWithAnEventHandler.Dispose();
                    someDisposableObjectWithAnEventHandler = null;
                }
                // If this is a WinForm/UI control, uncomment this code
                //if (components != null)
                //{
                //    components.Dispose();
                //}
            }
            // Release all unmanaged resources here  
            // (example)             if (someComObject != null && Marshal.IsComObject(someComObject))
            {
                Marshal.FinalReleaseComObject(someComObject);
                someComObject = null;
            }
        }
    }
    finally
    {
        this.IsDisposed = true;
    }
}

//TODO Uncomment this code if this class will contain members which are UNmanaged
///// <summary>Finalizer for MyDisposableClass</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>
//  ~MyDisposableClass()
//  {
//     Dispose( false );
//  }
#endregion IDisposable base-class implementation
 
Here is the code for properly implementing the IDisposable pattern in a derived class:

#region IDisposable derived-class implementation

/// <summary>
/// Gets or sets a value indicating whether this instance is disposed.
/// </summary>
/// <value>
///  <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
/// </value>
/// <remarks>Default initialization for a bool is 'false'</remarks>
private bool IsDisposed { get; set; }

/// <summary>
/// Overloaded Implementation of Dispose.
/// </summary>
/// <param name="isDisposing"><c>true</c> to release both managed and unmanaged resources; 
/// <c>false</c> to release only unmanaged resources.</param>
/// <remarks>
/// <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 <c>false</c>, 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>
/// </remarks>
protected override 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)
        {
            // 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.
            if (isDisposing)
            {
                // Release all managed resources here

                // Need to unregister/detach yourself from the events. Always make sure
                // the object is not null first before trying to unregister/detach them!
                // Failure to unregister can be a BIG source of memory leaks
                if (someDisposableObjectWithAnEventHandler != null)
                {                 
                    someDisposableObjectWithAnEventHandler.SomeEvent -= someDelegate;
                    someDisposableObjectWithAnEventHandler.Dispose();
                    someDisposableObjectWithAnEventHandler = null;
                }
                // If this is a WinForm/UI contrlol, uncomment this code
                //if (components != null)
                //{
                //    components.Dispose();
                //}
            }

            // Release all unmanaged resources here
 
 
            // (example)
            if (someComObject != null && Marshal.IsComObject(someComObject))
            {
                Marshal.FinalReleaseComObject(someComObject);
                someComObject = null;
            }
        }
    }
    finally
    {
        this.IsDisposed = true;

        // explicitly call the base class Dispose implementation
        base.Dispose(isDisposing);
    }
}
#endregion IDisposable derived-class implementation

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM