非托管资源,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对象。

+0

查看我的更新回答 – 2012-04-24 15:44:39

不,你只需要实现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)实现池。

+0

非常感谢您的详细解答,非常感谢! – Pantelis 2012-04-25 05:48:00

Operation()已完成后,将处理该方法中使用的所有非托管资源。没有理由实施IDisposableMyClass不保留任何非托管资源,因此它不需要实现该接口。

关于你的第二个问题,你的类的实例会像其他被管理对象一样被垃圾回收。

不,不需要实现IDisposable接口,你没有资源释放。