2011-12-01 53 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 
}