2011-12-01 59 views
0

我想弄清楚如何控制何时我的自定义对象被垃圾收集器收集 - 我发现了很多引用来使用IDisposable/Destructor来做这一点,但每一个例子都有类似以下内容:清理资源(垃圾回收,使用,IDisposable等)

class Car 
{ 
    ~Car() // destructor 
    { 
     // cleanup statements... 
    } 
} 

(http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx)

其实云在“清理语句什么“?

我希望能够在程序关闭时使用对象的实例调用CarInstance.Dispose()并让GC清理该特定实例 - 这样,当出现性能问题时,我将不会出现尖峰GC自动运行并清理一堆 -

让我知道! 威廉

+0

我喜欢这个SO环节 - 它具有对整个问题的一些很大的联系,对双方析构函数和IDisposable的触动:http://stackoverflow.com/questions/3649066/use-of-destructor-in-c – dash

回答

1

这取决于你所说的“清理”的东西 -

如果你刚刚提到释放托管内存,那么有没有直接的方法来清理你的对象的内存,只是你的对象。事实上,你不想这样做 - GC是高效的,而试图“控制”它往往会扰乱它的启发式。这是直接调用GC.Collect的原因之一。

如果您正在管理资源(如本机资源)或必须发布的其他类似概念,那么IDisposable即可。但是,您应该正确实施它,这与您的示例代码非常不同。有关正确实施的详细信息,您可以看到我的series on IDisposable

2

如果您需要清理非托管资源,那么.Net无法自动清理,您应该只创建一个终结器。

如果您需要清理昂贵的托管或非托管资源,则应该执行IDisposable。昂贵并不意味着记忆;一个“昂贵”的管理资源意味着围绕一些不受管理的东西(如文件,流,GDI +等)

强制GC收集特定对象是不可能的。

0

如果您想要控制何时放置特定对象,请为其执行IDisposable并明确呼叫obj.Dispose()

1

除极少数情况外,您不应该尝试'控制GC'。几乎可以保证你不会遇到这种情况。永远。

IDisposable.Dispose()不是真的(直接)与GC或析构函数相关。

  • Dispose()是不是内存清理托管资源,等。它需要由您的代码明确调用。作为备份,一些类在析构函数中调用它。但应该在此之前调用它。
  • 析构函数用于清理非托管资源,通常也是内存以外的资源。但你也应该在Dispose()也这样做。
  • GC自动运行并完成其工作 - 清理对象使用的内存。你通常不应该试图大惊小怪。
0

要调用CarInstance.Dispose(),它必须实现IDisposable然后终结应该调用Dispose(false),让所有的清理代码是在一个位置。

按照此question中引用的Finalize/Dispose模式。

至于应该在“清理声明”中应该包含哪些代码,清理任何非托管资源。 .NET无法自行清理的东西。

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 
}