C# 正确实现IDisposable
在我的类中,我实现了C# 正确实现IDisposable,c#,.net,memory-management,memory-leaks,garbage-collection,C#,.net,Memory Management,Memory Leaks,Garbage Collection,在我的类中,我实现了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 = User
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,但我不确定我在这里做错了什么。全文如下:
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;
}
}
CA1063 Implement IDisposable在“User”上正确提供可重写的Dispose(bool)实现,或将类型标记为sealed。调用Dispose(false)应该只清理本机资源。调用Dispose(true)应该清除托管资源和本机资源。stman User.cs 10
供参考:
我已经看完了这一页,但恐怕我真的不明白这里需要做什么
如果有人能用更通俗的语言解释问题所在和/或应该如何实现
IDisposable
,那将非常有帮助 IDisposable
的存在为您提供了一种清理非托管资源的方法,这些资源不会被垃圾收集器自动清理
您正在“清理”的所有资源都是托管资源,因此您的
Dispose
方法一事无成。您的类根本不应该实现IDisposable
。垃圾收集器将自行处理所有这些字段。首先,您不需要“清理”字符串和int
s-垃圾收集器将自动处理这些字段。在Dispose
中唯一需要清理的是实现IDisposable
的非托管资源或托管资源
但是,假设这只是一个学习练习,建议实施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;
}
}
您需要像这样使用一次性模式:
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);
}
这将是正确的实现,尽管我在您发布的代码中没有看到任何需要处理的内容。只有在以下情况下,才需要实现
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()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// free managed resources
}
// free native resources if there are any.
}
}
由于类不获取任何非托管资源(文件、数据库连接等),因此您无需将
User
类设置为IDisposable
。通常,我们把班级标记为
IDisposable
如果它们至少有一个IDisposable
字段或/和属性。
在实施IDisposable
时,最好按照微软的典型方案:
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
}
}
创建和使用Users类时,请使用“using”块以避免显式调用dispose方法:
using (Users _user = new Users())
{
// do user related work
}
using block end created Users对象将通过dispose方法的隐式调用进行处置。以下示例显示了实现
IDisposable
接口的一般最佳实践
请记住,只有在类中有非托管资源时,才需要析构函数(终结器)。如果添加析构函数,则应在Dispose中禁止终结,否则将导致对象在内存中驻留两个垃圾周期(注意:)。下面的例子详细说明以上所有内容
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.
}
}
我看到很多Microsoft Dispose模式的例子,它实际上是一种反模式。正如许多人指出的,问题中的代码根本不需要IDisposable。但是如果您想在哪里实现它,请不要使用Microsoft模式。更好的答案是遵循本文中的建议:
唯一可能有用的另一件事是抑制代码分析警告 这是
Dispose
中的所有代码吗?您应该使用/调查IDisposable模式。我相信你很快就会得到很多详细的答案,但基本上它涉及到GC.superssFinalize()
和析构函数等。你应该实现Dispose()方法来调用类中任何成员的Dispose()方法。这些成员都没有。因此,不应实现IDisposable。重置属性值是毫无意义的。如果要处置非托管资源(包括已包装的非托管资源(SqlConnection
,FileStream
等),则只需实现idisable
)。如果您只有这里这样的托管资源,您不应该也不应该实现IDisposable
。这是代码分析的一个主要问题。它非常擅长检查愚蠢的小规则,但不擅长检查概念错误。因此,不要投反对票,也不要投反对票,将帖子保留为零,并以一个有用的poi结束问题当我开始用C#编写时,有人告诉我最好使用using(){}
只要有可能,但要做到这一点,您需要实现IDisposable,因此一般来说,我更喜欢通过使用来访问类,特别是在我只需要一两个类的情况下functions@Ortund您误解了。当类实现IDisposable时,最好使用using
块。如果您不需要可丢弃的类,请不要使用实现它。它没有任何用途。@DanielMann使用
块的的语义往往不仅仅是IDisposable
接口本身的吸引力。我想,IDisposable
的滥用不仅仅是为了范围的目的。如果您有任何非托管资源可以使用,这只是一个附带说明您应该包括Finalizer调用Dispose(false),这将允许GC在执行垃圾收集时调用Finalizer(如果尚未调用Dispose),并正确释放非托管资源。如果实现中没有Finalizer调用GC.SuppressFinalize(this);
是指针