C# 清理资源(垃圾收集、使用、IDisposable等)
我试图弄清楚如何控制垃圾收集器何时收集我的自定义对象-我找到了很多关于使用IDisposable/destructor来完成此操作的参考资料,但每个示例都有如下内容:C# 清理资源(垃圾收集、使用、IDisposable等),c#,garbage-collection,idisposable,C#,Garbage Collection,Idisposable,我试图弄清楚如何控制垃圾收集器何时收集我的自定义对象-我找到了很多关于使用IDisposable/destructor来完成此操作的参考资料,但每个示例都有如下内容: class Car { ~Car() // destructor { // cleanup statements... } } (http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx) “清理语句”中到底有什么内容 我希望能够在我的程
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
(http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx)
“清理语句”中到底有什么内容
我希望能够在我的程序停止运行对象的实例时调用CarInstance.Dispose(),并让GC清理该特定实例-这样,当GC自动运行并清理一堆实例时,我就不会出现性能问题的峰值-
让我知道!
威廉这取决于你所说的“清理”是什么意思- 如果您只是指释放托管内存,那么没有直接的方法来清理对象的内存,只有对象。事实上,您不想这样做-GC是高效的,试图“控制”它往往会弄乱它的启发式。这就是为什么直接调用
GC.Collect
是个坏主意的部分原因
如果您正在管理资源,例如本机资源或其他必须发布的类似概念,那么
IDisposable
就是一种方法。但是,您应该正确地实现它,这与示例代码非常不同。有关正确实现的详细信息,请参见我的。这取决于您所说的“清理”是什么意思-
如果您只是指释放托管内存,那么没有直接的方法来清理对象的内存,只有对象。事实上,您不想这样做-GC是高效的,试图“控制”它往往会弄乱它的启发式。这就是为什么直接调用GC.Collect
是个坏主意的部分原因
如果您正在管理资源,例如本机资源或其他必须发布的类似概念,那么
IDisposable
就是一种方法。但是,您应该正确地实现它,这与示例代码非常不同。有关正确实现的详细信息,请参见我的。如果需要清理.Net无法自动清理的非托管资源,则只应创建终结器
如果需要清理昂贵的托管或非托管资源,则应实现IDisposable
。昂贵并不意味着记忆;“昂贵的”托管资源是指非托管资源(如文件、流、GDI+等)的包装器
无法强制GC收集特定对象。只有在需要清理.Net无法自动清理的非托管资源时,才应创建终结器 如果需要清理昂贵的托管或非托管资源,则应实现
IDisposable
。昂贵并不意味着记忆;“昂贵的”托管资源是指非托管资源(如文件、流、GDI+等)的包装器
无法强制GC收集特定对象。如果要控制何时释放特定对象,请为其实现并显式调用
obj.Dispose()
。如果要控制何时释放特定对象,请为其实现并调用obj.Dispose()
明确。除非在极少数情况下,否则不应尝试“控制GC”。几乎可以保证你不会遇到这种情况。永远
IDisposable.Dispose()
实际上与GC或析构函数没有(直接)关系
用于清理托管资源,而不是内存。它需要由代码显式调用。作为备份,一些类将对它的调用放入析构函数中。但应该在那之前打电话Dispose()
- 析构函数用于清理非托管资源,通常也是内存以外的资源。但您可能也应该在
中执行此操作Dispose()
- GC会自动运行,并且会很好地完成它的工作——它会清理对象使用的内存。你一般不应该对此大惊小怪
IDisposable.Dispose()
实际上与GC或析构函数没有(直接)关系
用于清理托管资源,而不是内存。它需要由代码显式调用。作为备份,一些类将对它的调用放入析构函数中。但应该在那之前打电话Dispose()
- 析构函数用于清理非托管资源,通常也是内存以外的资源。但您可能也应该在
中执行此操作Dispose()
- GC会自动运行,并且会很好地完成它的工作——它会清理对象使用的内存。你一般不应该对此大惊小怪
CarInstance.Dispose()
,它必须实现IDisposable
,然后终结器应调用Dispose(false)
,以便所有清理代码都位于一个位置
遵循本文中引用的Finalize/Dispose模式
至于“Cleanup语句”中应该包含什么,它应该包含清理任何非托管资源的代码。NET无法自行清理的内容。要调用
CarInstance.Dispose()
,它必须实现IDisposable
,然后终结器应调用Dispose(false)
,以便所有清理代码都位于一个位置
遵循本文中引用的Finalize/Dispose模式
至于“Cleanup语句”中应该包含什么,它应该包含清理任何非托管资源的代码。NET无法自行清理的内容。这里是我用于存储库的基类的代码片段。它利用IDisposable接口来清理Linq到SQL上下文
/// <summary>
/// Base class for common functionality shared across Sql repositories.
/// </summary>
internal abstract class BaseSqlRepository : IDisposable
{
#region Members
/// <summary>
/// Linq to Sql data context
/// </summary>
private SqlRepositoryDataContext context;
/// <summary>
/// Determines whether the class has invoked the dispose/finalize functionality.
/// </summary>
private bool isDisposed;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="BaseSqlRepository"/> class.
/// </summary>
protected BaseSqlRepository()
{
this.context = new SqlRepositoryDataContext(InitializeConnectionString());
this.isDisposed = false;
}
protected BaseSqlRepository(SqlRepositoryDataContext Context)
{
this.context = Context;
this.isDisposed = false;
}
/// <summary>
/// Finalizes an instance of the BaseSqlRepository class.
/// Releases unmanaged resources and performs other cleanup operations before the
/// <see cref="BaseSqlRepository"/> is reclaimed by garbage collection.
/// </summary>
~BaseSqlRepository()
{
this.Dispose(false);
}
#endregion
#region Properties
/// <summary>
/// Gets or sets the context.
/// </summary>
/// <value>The context.</value>
protected SqlRepositoryDataContext Context
{
get { return this.context; }
set { this.context = value; }
}
#endregion
#region Methods
/// <summary>
/// Initializes the connection string.
/// </summary>
/// <returns>Connection string.</returns>
protected static string InitializeConnectionString()
{
string connectionName = ConfigurationManager.AppSettings["AppConnection"];
string connection = string.Empty;
if (!string.IsNullOrWhiteSpace(connectionName))
{
connection = ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;
if (string.IsNullOrWhiteSpace(connection))
{
throw new ArgumentException("Unable to initialize a connection to the database.");
}
}
else
{
throw new ArgumentException("Unable to initialize a connection to the database.");
}
return connection;
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected void Dispose(bool disposing)
{
if (!this.isDisposed && disposing)
{
// Dispose the managed resources of the class
this.context.Dispose();
}
// Dipose the un-managed resources of the class
this.isDisposed = true;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
//
///基类