c#内存分配和释放模式

c#内存分配和释放模式,c#,.net,memory-management,memory-leaks,C#,.net,Memory Management,Memory Leaks,因为C#使用垃圾收集。何时需要使用.Dispose释放内存 我意识到有一些情况,所以我会尽量列出我能想到的情况 如果我关闭一个包含GUI类型对象的表单,这些对象是否会被取消引用并因此被收集 如果我使用new创建一个本地对象,我应该在方法退出之前处理它,还是让GC处理它?在这种情况下,什么是良好做法 在任何时候强制GC都是可以理解的吗 GC在收集其对象时是否收集事件 看看这个问题: 如果您的类实例化IDisposable接口,这(可能)意味着它拥有必须直接处置的系统资源。实现这一点的一个简单方法

因为C#使用垃圾收集。何时需要使用.Dispose释放内存

我意识到有一些情况,所以我会尽量列出我能想到的情况

  • 如果我关闭一个包含GUI类型对象的表单,这些对象是否会被取消引用并因此被收集
  • 如果我使用new创建一个本地对象,我应该在方法退出之前处理它,还是让GC处理它?在这种情况下,什么是良好做法
  • 在任何时候强制GC都是可以理解的吗
  • GC在收集其对象时是否收集事件
  • 看看这个问题:

    如果您的类实例化IDisposable接口,这(可能)意味着它拥有必须直接处置的系统资源。实现这一点的一个简单方法是使用using关键字,如中所示:

    using(var g = Graphics.FromBitmap(bmp))
    {
        //Do some stuff with the graphics object
    }
    
    根据@Matt S在我提到的问题中的回答

    关于您的问题:

  • 如果实例化具有IDisposable的对象,则需要在关闭表单时处理该对象。这在WPF中很棘手,在Winforms中很简单,因为Winforms对话框有Dispose方法。对于WPF,我已经解决了这个问题,将WPF类保留在周围但隐藏起来,称为dispose方法,该方法处理所有对象(如串行端口),然后将WPF类设置为null
  • 不,让总司令来处理
  • 我想是的,但我得到了反对票:)当我做了很大的分配,迫使GC删除它们,依我看,是个好主意
  • 我不确定。我认为事件本身就是对象,因此在不再使用时将被收集

  • 理论上,如果您已经正确定义了componentry,那么在对象上调用Dispose()永远都不应该必需,因为终结器最终应该处理它

    也就是说,每当您使用实现IDisposable的对象时,最好在使用完该对象后立即对其调用Dispose()

    对于您的一些具体观点:

    1) 如果您知道表单已“完成”,则可以对其调用Dispose()。这将强制在该时间点清理和表单关联的非托管资源

    2) 在这种情况下:如果您的对象仅在该方法中使用,请改用“使用”:

    3) 很少有理由这样做,但总的来说,没有


    4) 事件是一个委托-与委托关联的内存将在委托本身解除根目录后收集,这通常发生在相关对象解除根目录时。

    您应该对每个实现IDisposable的类调用
    Dispose
    。如果它不需要
    Dispose
    ed,那么它就不会实现
    IDisposable

    至于你的其他问题:

  • 当您将控件添加到窗体的
    Controls
    集合时,该控件将在窗体关闭时自动释放,因此无需执行任何操作
  • 如果对象实现了
    IDisposable
    ,则需要调用
    Dispose
    。例如,如果您转到
    新文件流(…)
    ,则需要释放文件流,因为它实现了IDisposable。我建议您仔细阅读使用C#中的构造的
    ,这使得处理
    IDisposable
    对象更容易
  • 事实并非如此,99.99%的情况下,垃圾收集器会知道何时是最佳运行时间。这是一种“你会知道什么时候你需要它”的情况
  • 当包含事件的对象不再被引用时,从逻辑上讲,事件中包含的任何对象引用也不再被引用,并且将可用于收集

  • 如果您使用的是<代码> IDISPABLE < /COD>对象,请考虑使用<代码>使用语句来自动处理您的处理。

    如Reed Copsiy所说,通常不必调用Debug。

    可能会造成问题的一种情况是,静态对象持有其他对象的引用,而这些对象在其他任何地方都不再使用。以下代码显示了一个示例:

    Form_Load(...)
        MyState.Instance.AddressChanged += this.User_AddressChanged;
    End
    

    如果出于某种原因,在卸载表单时,代码未注销事件处理程序,则状态对象仍将引用表单实例。

    可能的重复:另请参阅:通常,对于不会返回的非托管资源,将实现IDisposable,当GC清理对象时关闭或最佳使用—托管对象始终由GC清理。请参见IDisposable@For#2,无论您是否调用Dispose(),GC都会处理托管代码中的对象#1和内置的“GUI类型对象”将被收集,无论您是否调用Dispose()。另请看@George:我不认为它们与任何一个都是重复的。我也许应该澄清一下,因为我的主要问题是什么时候应该明确地释放内存,什么时候不应该担心它。答案似乎很清楚,也就是说,如果一个对象可以被释放,那么它总是被释放,这是首选的模式。我将开始对所有一次性物品使用它,以遵循一致的模式。谢谢你的回答。你的回答似乎与其他人的回答相冲突。你为什么说让GC来处理?另外,它似乎与您的原始语句有一些冲突?如果您只是使用new创建一个对象,但它没有实现IDisposable接口,那么让GC来处理它。但是,如果它实现了IDisposable,那么您必须按照#1的规定在释放它之前处理它。如果声明一个新的int数组,int不会实现IDisposable,因此您可以让gc来处理它。#1:True但是如果对象是在设计时添加的,但没有添加到控件的集合中呢?当窗体关闭时,它是否仍将被释放
    Form_Load(...)
        MyState.Instance.AddressChanged += this.User_AddressChanged;
    End