C# 清理资源(垃圾收集、使用、IDisposable等)

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) “清理语句”中到底有什么内容 我希望能够在我的程

我试图弄清楚如何控制垃圾收集器何时收集我的自定义对象-我找到了很多关于使用IDisposable/destructor来完成此操作的参考资料,但每个示例都有如下内容:

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会自动运行,并且会很好地完成它的工作——它会清理对象使用的内存。你一般不应该对此大惊小怪

除非在极少数情况下,否则不应尝试“控制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
}
//
///基类