C# I';我不确定是否需要手动';清理';我的对象,或者垃圾收集器是否会处理它

C# I';我不确定是否需要手动';清理';我的对象,或者垃圾收集器是否会处理它,c#,.net,C#,.net,我一直在研究,但我很难理解我需要做什么(如果有的话),以确保我的对象在某些情况下得到适当的“照顾” 我知道我应该使用using(即Dispose())的语法糖)来确保我正在释放非托管资源,但是,当我创建临时对象时,我不确定我是否需要做些什么来主动释放它,或者垃圾收集器是否会像处理临时变量一样处理它 例如: public void LoadSerializedClass(string filePath) { Binary formatter = new BinaryFormatter(

我一直在研究,但我很难理解我需要做什么(如果有的话),以确保我的对象在某些情况下得到适当的“照顾”

我知道我应该使用
using
(即
Dispose()
)的语法糖)来确保我正在释放非托管资源,但是,当我创建临时对象时,我不确定我是否需要做些什么来主动释放它,或者垃圾收集器是否会像处理临时变量一样处理它

例如:

public void LoadSerializedClass(string filePath) 
{ 
    Binary formatter = new BinaryFormatter(); 

    if (File.Exists(filePath))
    {
        using (Stream input = File.OpenRead(filePath))
        {
            MySerializedClass mySerializedClass 
                = (MySerializedClass)formatter.Deserialize(input); 

            /* ... use the deserialized class ... */ 

            /* ... the deserialized class is no longer needed... */
        } 
    }
} 
  • 我使用
    using
    来确保非托管资源得到正确处置

  • (目前)我没有做任何事情来处理我的
    MySerializedClass
    的临时实例(打算成为临时实例)——我(可能是非常错误地)认为它会像本地临时变量一样工作,我不需要管理它。我错了吗?我从我做的研究中得到的印象是,我不必做任何事情,垃圾收集器会自动把它捡起来;然而,一位同事给我的印象不同,我显然很难理解


谢谢大家!

您只需要处理实现IDisposable的对象。你的变量很好。即使对于实现IDisposable的对象,如果您不处理它们,GC也会在某个时候将其删除。问题是非托管资源在此期间不会被释放,您可能会使操作系统缺少该资源或导致其他问题。例如,如果您打开一个文件而不关闭它,操作系统会认为该文件正在使用,不会让用户删除它。GC最终将收集托管对象并释放文件,但如果您的程序没有内存压力,这可能需要相当长的时间

有关GC如何工作的更多信息,您可能希望查看一些关于它的文章。基本上,如果GC决定它需要释放一些内存,它将从作用域中的所有变量+所有静态字段开始,遍历它们引用的所有对象,然后递归地向下遍历。标记完成后,只删除未标记的对象。这叫做标记和扫描(GC有不同的策略,这只是其中之一)。GC不查找未使用的对象,而是查找已使用的对象并删除其余的对象


至于IDISPOLIDE,一个正确实现的IDISPOSILL将有一个终结器(语法就像C++ +析构函数~)。如果GC看到一个带有终结器的对象,它会在删除对象之前记录调用它。通常,终结器将执行Dispose方法将执行的操作,并释放非托管对象。但是请注意,GC只关心程序使用的内存,因此它不关心文件句柄或网络连接。也许操作系统需要这些资源,但从GC的角度来看,一切都很好,因为有足够的内存,而且不想调用这些终结器。这就是我们明确需要释放(dispose)非托管资源的原因。

如果类没有实现
IDisposable
,那么您不需要做任何事情。对所有实现
IDisposable
的对象使用
using
dispose()
,您就完成了。所有其他对象引用都会被处理好的。。。如果类本身使用非托管资源,我只会实现
IDisposable
,对吗?@crashmstr那么对象引用是否有效地在本地作用域?它实际上是如何工作的?由于保存对对象引用的变量不再存在,是否实际上没有对对象的引用,因此垃圾收集器将清理它?是这样吗?还是我误解了?@Eilidh一旦没有对象的引用,它就可以被垃圾收集。如果您将该引用放入一个长寿命的
列表
,那么它将至少与该列表一样长。重点是,你不必担心,谢谢。垃圾收集器如何“知道”处理对象?是否持有对它的引用的变量只在本地存在,因此当变量“消失”时,不再有对对象的引用,垃圾收集器知道如何清除它?是的-一旦程序超出变量的作用域,它就有资格进行收集(或者更早,如果编译器已经做了一些优化技巧)。@Eilidh这是一个很大的问题。如果您实现了@Eilidh,那么垃圾收集器将调用终结器。这将确保即使
Dispose()
未被调用。@Mgetz终结器的调用与Dispose模式无关-它是一种模式,而不是语言功能。