非托管资源,IDisposable接口和自定义类型
作为我厌倦了阅读了无数话题找到一个答案,我的问题:)非托管资源,IDisposable接口和自定义类型
主题的另一个话题假设我们有下面的类:
public class MyClass
{
private const string conString = "connection string";
private int Operation()
{
int count = 0;
using(var con = SqlConnection(conString))
{
string select_cmd = "SELECT * FROM TABLE";
using(var cmd = new SqlCommand(select_cmd, con))
{
using(var reader = cmd.ExecuteReader())
{
while(reader != null && reader.Read())
count++;
}
}
}
return count;
}
}
由于连接到数据库是在using语句中实例化的,因此con.close()和condispose()方法将被调用,是否需要为MyClass实现IDisposable? MyClass在超出范围时会被垃圾收集吗?
编辑:
谢谢您的回复,这就是我的想法,但我需要说清楚。还有一个问题。
如果我的类有几个Operations()在数据库上做一些工作,从资源消耗的角度来看,有一个SqlConnection成员是更好的做法,在类构造函数中实例化并打开它并实现IDisposable关闭它而不是在每个操作中使用“using”语句(在每个操作中打开和关闭数据库)? 这种方式我只应该在使用语句中实例化和使用MyClass对象。
不,你只需要实现IDisposable,如果你的类在Operation()方法之外持有SqlConnection实例,这样它就保持与类本身一起存在(例如,如果你将它分配给类成员字段或属性)。
在您的类超出范围之前,SqlConnection实例将被标记为符合清理条件,因为该实例超出了使用块中的范围。最重要的是非受控数据库连接(由SqlConnection封装)已通过Dispose调用释放。当GC感到有足够的压力来证明进行GC通行证时,SqlConnection的受管部分将被释放。
至于你的类实例,它也会在GC的判断中被释放,这是你不需要关心的东西,除非你在整个生命周期中创建和销毁大量的类实例你的应用程序(数百万我想)。
编辑
关于第二个问题,它是更好地使用和每个方法处理SqlConnection的实例,因为这个特殊的数据库客户端类内部实现连接池(即:它并不真正关闭连接,当你处理一段时间,这样当创建一个新的SqlConnection时,它会重新使用打开的连接池中的一个)。
见(旧的,但有效):http://msdn.microsoft.com/en-us/library/8xx3tyca%28v=vs.71%29.aspx
如果您使用数据库客户端API没有实现自己的汇集,它也许不如手动你建议管理此。但是,您必须小心同步对连接的访问(即:不要让2个线程同时使用它)并自行管理生命周期问题(例如:如果您的课程在应用程序的所有持续时间内保持活动状态,将持有无限期打开的数据库资源等)
大多数现代的(MySql Connector.NET,SQL Server)实现池。
非常感谢您的详细解答,非常感谢! – Pantelis 2012-04-25 05:48:00
Operation()
已完成后,将处理该方法中使用的所有非托管资源。没有理由实施IDisposable
。 MyClass
不保留任何非托管资源,因此它不需要实现该接口。
关于你的第二个问题,你的类的实例会像其他被管理对象一样被垃圾回收。
不,不需要实现IDisposable接口,你没有资源释放。
查看我的更新回答 – 2012-04-24 15:44:39