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