非托管资源、可识别和自定义类型
本文关键字:识别 自定义 类型 资源 | 更新日期: 2023-09-27 18:32:02
该主题的另一个主题,因为我厌倦了阅读无数主题以找到问题的答案:)
假设我们有以下类:
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() 和最终的 con.dispose() 方法,是否需要为 MyClass 实现 IDisposable?MyClass超出范围时会被垃圾收集吗?
编辑:
谢谢你的回复,这就是我的想法,但我需要说清楚。还有一个问题。
如果我的类有几个在数据库上做一些工作的 Operations(),那么从资源消耗的角度来看,拥有一个 SqlConnection 成员,在类构造函数上实例化并打开它并实现 IDisposable 来关闭它而不是在每个操作中使用"using"语句(在每个操作上打开和关闭数据库)?当然,这样我应该只在 using 语句中实例化和使用 MyClass 对象。
不,只有当你的类在 Operation() 方法之外保留 SqlConnection 实例时,你才需要实现 IDisposable,这样它与类本身保持活动状态(例如,如果你正在将其辅助到类成员字段或属性)。
在您的类超出范围之前,SqlConnection 实例将被标记为符合清理条件,因为该实例在 using 块中超出了范围。最重要的是,非托管数据库连接(由 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)都实现了池化。
Operation()
完成后,将释放该方法中使用的所有非托管资源。它没有理由实施IDisposable
. MyClass
不会使任何非托管资源保持打开状态,因此不需要实现该接口。
关于第二个问题,类的实例将像任何其他托管对象一样被垃圾回收。
不,不需要实现到 IDisposable 接口,您没有资源可以释放。