我试图找出如何控制垃圾收集器收集自定义对象的时间 - 我发现很多引用使用IDisposable / Destructors来执行此操作但是每个示例都有如下内容:
class Car
{
~Car() // destructor
{
// cleanup statements...
}
}
(http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx)
“清理声明”中究竟出现了什么?
我希望能够在我的程序关闭时使用该对象的实例调用CarInstance.Dispose()并让GC清理该特定实例 - 这样我在GC时就不会出现性能问题高峰自动运行并清理一堆 -
让我知道! 威廉
答案 0 :(得分:2)
如果您需要清理.Net无法自动清理的非托管资源,则只应创建终结器。
如果需要清理昂贵的托管或非托管资源,则应实施IDisposable
。昂贵并不意味着记忆; “昂贵的”托管资源意味着包装非托管的东西(例如,文件,流,GDI +等)
无法强制GC收集特定对象。
答案 1 :(得分:1)
这取决于你所说的“清理” -
如果你只是提到发布托管内存,那么没有直接的方法来清理对象的内存,只有你的对象。事实上,你不想这样做 - GC非常高效,并试图“控制”它往往会搞砸它的启发式。这是直接调用GC.Collect
是个坏主意的部分原因。
如果您正在管理资源,例如本机资源或必须发布的其他类似概念,那么IDisposable
是可行的方法。但是,您应该正确实现它,这与您的示例代码非常不同。有关正确实施的详细信息,您可以看到我的series on IDisposable。
答案 2 :(得分:1)
除极少数情况外,你不应该试图“控制GC”。几乎可以保证你不会遇到这种情况。如初。
IDisposable.Dispose()
并非(直接)与GC或析构函数相关。
Dispose()
用于清理托管资源,以外的内存。它需要由您的代码显式调用。作为备份,一些类在析构函数中调用它。但是应该在此之前调用它。Dispose()
中这样做。答案 3 :(得分:0)
如果您想控制何时处置特定对象,请为其实施IDisposable并明确调用obj.Dispose()
。
答案 4 :(得分:0)
要致电CarInstance.Dispose()
,必须实施IDisposable
然后终结器应调用Dispose(false)
,以便所有清理代码都在一个位置。
遵循此question中引用的Finalize / Dispose模式。
至于“清理语句”中应包含的内容,这应包含清除任何非托管资源的代码。 .NET无法自行清理的事情。
答案 5 :(得分:0)
以下是我用于存储库的基类代码片段。它利用IDisposable接口来清理Linq-to-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
}