正确实施IDisposable
在我的课程中,我实现了IDisposable,如下所示:
public class User : IDisposable { public int id { get; protected set; } public string name { get; protected set; } public string pass { get; protected set; } public User(int UserID) { id = UserID; } public User(string Username, string Password) { name = Username; pass = Password; } // Other functions go here... public void Dispose() { // Clear all property values that maybe have been set // when the class was instantiated id = 0; name = String.Empty; pass = String.Empty; } }
在VS2012,我的代码分析说正确实施IDisposable,但我不知道我在这里做错了什么。
确切的文字如下:
CA1063正确实现IDisposable在“用户”上提供Dispose(bool)的可覆盖实现,或将该types标记为密封。 调用Dispose(false)应该只清理本地资源。 调用Dispose(true)应该清理托pipe资源和本地资源。 stman User.cs 10
供参考: CA1063:正确实施IDisposable
我已经阅读了这个页面,但是恐怕我不太明白这里需要做什么。
如果任何人可以更清楚地解释问题是什么和/或如何实施IDisposable,这将真的帮助!
这将是正确的实现,虽然我没有看到你需要在你发布的代码中处置任何东西。 您只需要在以下情况下实施IDisposable
:
- 你有非托pipe资源
- 你坚持引用本身是一次性的东西。
您发布的代码中没有任何内容需要处理。
public class User : IDisposable { public int id { get; protected set; } public string name { get; protected set; } public string pass { get; protected set; } public User(int userID) { id = userID; } public User(string Username, string Password) { name = Username; pass = Password; } // Other functions go here... public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { // free managed resources } // free native resources if there are any. } }
首先,你不需要“清理” string
和int
,它们将被垃圾收集器自动处理。 Dispose
中唯一需要清理的是非托pipe资源或实现IDisposable
托pipe资源。
但是,假设这只是一个学习练习, 推荐使用 IDisposable
是添加一个“安全捕获”来确保任何资源不会被处理两次:
public void Dispose() { Dispose(true); // Use SupressFinalize in case a subclass // of this type implements a finalizer. GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Clear all property values that maybe have been set // when the class was instantiated id = 0; name = String.Empty; pass = String.Empty; } // Indicate that the instance has been disposed. _disposed = true; } }
以下示例显示了实现IDisposable
接口的一般最佳实践。 参考
请记住,只有在您的类中有非托pipe资源时,才需要析构函数(终结器)。 如果你添加一个析构函数,你应该在Dispose中压缩Finalization ,否则它将导致你的对象驻留在内存中两个垃圾周期(注意: 读取Finalization如何工作 )。 以上例子详细阐述。
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. } }
IDisposable
存在为您提供一种方法来清理垃圾收集器不会自动清理的非托pipe资源。
您“清理”的所有资源都是托pipe资源,因此您的Dispose
方法完成任何操作。 你的课不应该实现IDisposable
。 垃圾收集者将自行处理所有这些领域。
你需要像这样使用一次性模式 :
private bool _disposed = false; protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // Dispose any managed objects // ... } // Now disposed of any unmanaged objects // ... _disposed = true; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } // Destructor ~YourClassName() { Dispose(false); }
您不需要将您的User类设置为IDisposable,因为该类不会获取任何非pipe理资源(文件,数据库连接等)。 通常,如果类至less有一个IDisposable字段或/和属性,则将其标记为IDisposable。 在实现IDisposable的时候,最好按照微软的典型scheme:
public class User: IDisposable { ... protected virtual void Dispose(Boolean disposing) { if (disposing) { // There's no need to set zero empty values to fields // id = 0; // name = String.Empty; // pass = String.Empty; //TODO: free your true resources here (usually IDisposable fields) } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }
无论何时您想要一个确定性的(确认的)垃圾收集,都可以使用Idisposable。
class Users : IDisposable { ~Users() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); // This method will remove current object from garbage collector's queue // and stop calling finilize method twice } public void Dispose(bool disposer) { if (disposer) { // dispose the managed objects } // dispose the unmanaged objects } }
创build和使用Users类时,使用“using”块来避免显式调用dispose方法:
using (Users _user = new Users()) { // do user related work }
使用块创build的Users对象的末端将通过隐式调用dispose方法进行处理。