C# 我们是否需要将自定义类的对象设置为null,或者GC将处理它

C# 我们是否需要将自定义类的对象设置为null,或者GC将处理它,c#,class,garbage-collection,idisposable,C#,Class,Garbage Collection,Idisposable,请看下面给出的示例代码。我有两个问题: 1.我们是否需要在返回某些内容之前关闭数据读取器,或者GC会处理它? 2.我们是否需要将自定义类对象设置为null,或者GC将在这两种情况下处理它 public class Database { public string DoSomething() { using (SqlConnection con = new SqlConnection(connectionString)) {

请看下面给出的示例代码。我有两个问题:
1.我们是否需要在返回某些内容之前关闭数据读取器,或者GC会处理它?
2.我们是否需要将自定义类对象设置为null,或者GC将在这两种情况下处理它

public class Database
{
    public string DoSomething()
    {
        using (SqlConnection con = new SqlConnection(connectionString))
        {
            using (SqlCommand cmd = new SqlCommand("Select ID,Name From Person", con))
            {
                SqlDataReader reader = cmd.ExecuteReader();

                while(reader.Read())
                {
                    return reader["Name"].ToString();
                    //will this close reader once string is returned or we have to close it?
                }
            }
        }
    }
}
用法

另一类

public class XML
    {
        public void ReadXML()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load("somefile.xml");
        }
    }
用法

XML xml = new XML();
xml.ReadXML();
xml = null; //is it necessary to do this or GC will take care of it?
TL;DR
SqlReader
中缺少一个
using
语句。其他场景由GC处理。如果对实现了
IDisposable
接口的对象进行了处理,请始终使用
Dispose
using
(最后一个注意事项中有一些例外)

注: 有关生命周期和范围的“副标题”差异,请参见@Damien_异教者的评论。有关垃圾回收的更多信息,请参阅MSDN:

通常,所有没有未完成引用的托管对象都将由GC处理。所以一般来说,您不需要显式地将它们设置为null

但是,如果对象实现了
IDisposable
接口,则最好在处理完对象后调用
Dispose
。尽管(如果正确实现),这也将在
Finalize
调用期间调用,但最好调用
Dispose
explicit(或通过
using
语句)。对象(如数据库连接、图形对象或网络连接)可能导致连接池已满或占用图形内存

请注意,这与范围和未完成的参考文献有关

如果您有这样的方法,则
对象
“behind”
数据库
将在离开作用域后立即处理,因为没有其他变量引用此对象:

public void Foo()
{
   Database database = new Database();
   string res = database.DoSomething();
   //you don't need this call 
   // because the will be no outstanding references after the method exits.
   //database = null;
}
但是,如果包含的对象是静态的或以另一种方式保持活动状态,则会出现这种情况;只要对该
FooClass
对象的某个地方存在有效引用,
数据库将保持活动状态:

public class FooClass
{
    Database database = new Database();

    public void Foo()
    {  
        //some operation
    }    
}
如果成员实现了
IDisposable
,最好使用
语句或显式(
Dispose()
)通过
调用它。尽管GC应该处理这个问题,特别是对于第三方库,但它需要正确实现
IDisposable
。如果您看到这个示例,您可以看到它可能很棘手,因此在面临内存泄漏时是可疑的

因此,要回答您的问题,请执行以下操作:

在下面的语句中,
using
语句相当于一个
try,catch finaly
块。看

到目前为止,我认为这些信息足以回答有关GC的问题。不过有一点值得注意;如果您面对的是非托管对象,则需要进行其他调用才能正确处理<例如,code>COM
需要
Marshall.ReleaseComObject()
,一些库(我知道的一些工业摄像头驱动程序)需要显式的
CleanUp
调用

TL;DR
SqlReader
中缺少一个
using
语句。其他场景由GC处理。如果对实现了
IDisposable
接口的对象进行了处理,请始终使用
Dispose
using
(最后一个注意事项中有一些例外)

注: 有关生命周期和范围的“副标题”差异,请参见@Damien_异教者的评论。有关垃圾回收的更多信息,请参阅MSDN:

通常,所有没有未完成引用的托管对象都将由GC处理。所以一般来说,您不需要显式地将它们设置为null

但是,如果对象实现了
IDisposable
接口,则最好在处理完对象后调用
Dispose
。尽管(如果正确实现),这也将在
Finalize
调用期间调用,但最好调用
Dispose
explicit(或通过
using
语句)。对象(如数据库连接、图形对象或网络连接)可能导致连接池已满或占用图形内存

请注意,这与范围和未完成的参考文献有关

如果您有这样的方法,则
对象
“behind”
数据库
将在离开作用域后立即处理,因为没有其他变量引用此对象:

public void Foo()
{
   Database database = new Database();
   string res = database.DoSomething();
   //you don't need this call 
   // because the will be no outstanding references after the method exits.
   //database = null;
}
但是,如果包含的对象是静态的或以另一种方式保持活动状态,则会出现这种情况;只要对该
FooClass
对象的某个地方存在有效引用,
数据库将保持活动状态:

public class FooClass
{
    Database database = new Database();

    public void Foo()
    {  
        //some operation
    }    
}
如果成员实现了
IDisposable
,最好使用
语句或显式(
Dispose()
)通过
调用它。尽管GC应该处理这个问题,特别是对于第三方库,但它需要正确实现
IDisposable
。如果您看到这个示例,您可以看到它可能很棘手,因此在面临内存泄漏时是可疑的

因此,要回答您的问题,请执行以下操作:

在下面的语句中,
using
语句相当于一个
try,catch finaly
块。看


到目前为止,我认为这些信息足以回答有关GC的问题。不过有一点值得注意;如果您面对的是非托管对象,则需要进行其他调用才能正确处理<例如,code>COM
需要
Marshall.ReleaseComObject()
,一些库(我知道的一些工业摄像头驱动程序)需要显式的
CleanUp
调用

对于您的第一个示例,我认为您混淆了范围和生命周期。如果您在发布模式下运行,JIT编译器和GC将相互协作以了解实际的生命周期。如果您的评论部分实际上包含大量耗时的co