C#可识别

C#可识别,c#,memory-leaks,dispose,idisposable,C#,Memory Leaks,Dispose,Idisposable,有人能解释一下,如果您不DisposesomeIDisposable实体(通过使用或直接Dispose调用),可能会发生什么情况吗 这是否总是导致内存泄漏,如果是,那么C#内存泄漏是否类似于C++内存泄漏,它们很容易导致崩溃,或者从这个角度看C#沙箱更安全 谢谢。不调用.Dispose()可能会导致内存泄漏。否则,不调用Dispose()只会导致GC延迟收集。总的来说,效果完全取决于实例化了哪些对象()。可以说,通过实施IDisposable,您负责清理您的混乱 实现应该做的是告诉GC(垃圾收集

有人能解释一下,如果您不
Dispose
some
IDisposable
实体(通过
使用
或直接
Dispose
调用),可能会发生什么情况吗

这是否总是导致内存泄漏,如果是,那么
C#
内存泄漏是否类似于
C++
内存泄漏,它们很容易导致崩溃,或者从这个角度看
C#
沙箱更安全

谢谢。

不调用.Dispose()可能会导致内存泄漏。否则,不调用Dispose()只会导致GC延迟收集。总的来说,效果完全取决于实例化了哪些对象()。可以说,通过实施IDisposable,您负责清理您的混乱

实现应该做的是告诉GC(垃圾收集器)它应该禁止收集,因为您要处理它。这样,当对IDisposable对象调用Dispose()方法时,您应该注意清理,即对该类中的对象调用Dispose(),清除集合等

并且,仅供参考,
using{…}
子句只能用于实现IDisposable的对象,因为在右括号处会自动调用Dispose()方法:

using (MyDisposableObject dispObj = new MyDisposableObject())
{
    // use dispObj for some work
}    // dispObj.Dispose() is automatically called here

这完全取决于所讨论的对象

对象实现IDisposable有四个原因:

  • 它拥有本地资源。
    如果是这样,它应该在其终结器中调用
    Dispose
    ,因此,如果您忘记对其进行处置,则只会导致本机资源的使用时间过长。
    如果您一次创建了很多这样的对象,但没有将它们处理掉,则可能会耗尽本机资源

  • 它拥有可一次性使用的托管对象。
    它拥有的物品也将属于这些类别之一;参见相关类别

  • 它对自身有一个持久的引用,不会自然释放(例如,它处理
    静态事件)
    dispose方法将清除此引用(例如,注销事件处理程序)
    如果是这样,不调用
    Dispose
    将导致它永远持续

  • 它继承了一个一次性基类,例如
    组件
    ,但实际上不需要处理。(例如,
    MemoryStream

    如果是这样的话,不调用
    Dispose
    是无害的,除非将来类发生更改

  • 它在
    Dispose
    方法中执行一些操作,人们应该使用
    语句调用这些操作(例如,
    使用(Html.BeginForm(){…}

    如果是这样,不处理对象将破坏其全部目的,即执行该操作


  • 如果一个类可以自由地实现
    Dispose
    ,不管它们选择如何,都可能会发生很多事情

    通常处理的不是托管资源(通常会自行处理),而是非托管资源,如数据库连接、文件锁等

    一般来说,当垃圾回收进入终结器时,Disposed在终结器中被调用,但是,例如,如果您写入一个文件,而您没有关闭它(Dispose会关闭它),那么您将阻止任何其他程序(包括同一程序中的代码的其他部分)打开该文件(可能以只读模式除外)

    如果您保持数据库连接的时间超过必要时间,您可能会达到最大打开连接数,并停止应用程序使用数据库


    通常,如果一个类实现了
    IDisposable
    ,这意味着我有一些需要处理的东西,应该尽快处理,而不是等待垃圾收集器出现。

    IDisposable意味着包装非托管资源(即非.NET内存)。因此,如果您不处置它们,则会泄漏诸如打开的数据库连接、窗口句柄、文件句柄等内容。这取决于您未能处置的IDisposable类型


    因此,这并不是真正的内存泄漏,但它会导致性能下降,最终在非托管资源耗尽时崩溃。

    最可能的影响是资源锁定(例如,打开文件句柄而不关闭它-最终由终结器处理)或耗尽(例如,您执行绘图操作而不处理对象)

    如果内存压力不足以导致GC(将启动终结过程)及时使用更多的资源,这可能是一个问题,尤其是对于后一个问题。这会导致有用的错误,如“GDI+中发生了一般错误”


    写得不好的对象如果只有Dispose方法而没有终结器,可能会泄漏内存,但这种情况很少见。另一种可能是Dispose方法取消订阅静态事件。这也可能是一个严重的问题,并且会“泄漏”内存。

    值得指出的一个区别是,.NET管理内存,而不是资源
    IDisposable
    的设计使实现此接口的类的客户端可以确定地处理资源

    Joe Duffy在其题为:

    CLR的垃圾收集器(GC)不会 在管理内存方面,这是一项了不起的工作 直接分配给CLR对象,但 显然不是为了处理 具有非托管内存和托管操作系统 资源


    有些对象在其存在期间会对外部实体执行预期清理的操作。有一个非常严格的约定,即此类对象应在实际操作时实现IDisposable,并在IDisposable.Dispose()时执行任何所需的清理方法。系统允许对象在注意到它们已被放弃时请求通知,但不能保证