在阅读了线程 Is SqlCommand.Dispose enough? 和 Closing and Disposing a WCF Service 之后,我想问一下像 SqlConnection 或从 Stream 类继承的几个类,如果我使用 Close Dispose 而不是 Close,是否有影响?
在阅读了线程 Is SqlCommand.Dispose enough? 和 Closing and Disposing a WCF Service 之后,我想问一下像 SqlConnection 或从 Stream 类继承的几个类,如果我使用 Close Dispose 而不是 Close,是否有影响?
根据微软的指南,如果合适的话提供Close
方法是一个好的实践。这里是来自Framework design guidelines的引用
考虑在
Dispose()
之外提供Close()
方法,如果关闭是该领域的标准术语。在这样做时,重要的是您使Close
实现与Dispose
相同...
在大多数情况下,Close
和Dispose
方法是等效的。在SqlConnectionObject
的情况下,Close
和Dispose
的主要区别是:
应用程序可以调用
Close
多次。不会生成异常。如果您调用了
Dispose
方法,则SqlConnection
对象状态将被重置。如果您尝试在已释放的SqlConnection
对象上调用任何方法,您将收到异常。
也就是说:
Dispose
。使用using
块可以确保即使出现异常也会调用该方法。Close
方法。通常的答案是:这要视情况而定。不同的类以不同的方式实现IDisposable接口,需要您做必要的研究。
就SqlClient而言,推荐的做法如下:
using (SqlConnection conn = /* Create new instance using your favorite method */)
{
conn.Open();
using (SqlCommand command = /* Create new instance using your favorite method */)
{
// Do work
}
conn.Close(); // Optional
}
在连接上,您应该调用Dispose
(或Close
*)!不要等待垃圾回收器清理连接,否则这将占用池中的连接直到下一个GC周期(至少)。如果您调用Dispose
,则无需调用Close
,并且由于using
结构使处理Dispose
变得如此容易,因此实际上没有理由调用Close
。
连接会自动汇集,并且在连接上调用Dispose
/Close
不会在正常情况下物理关闭连接。不要尝试实现自己的汇集。 SqlClient
在从池中检索连接时执行清理操作(例如还原数据库上下文和连接选项)。
*如果您正在调用Close
,请确保以异常安全的方式执行它(即在catch或finally块中)。
conn.Close(); // 可选的
这不是可选的。这是多余和不必要的。你正在两次处理该对象,这将被某些代码分析工具标记为警告。 - Metalogicusing (var x = ..) { x.Dispose(); }
中,此时的x
确实被“disposed twice”。 - user2864740就 SqlConnection
来说,从连接本身的角度来看,它们是等效的。根据 Reflector,Dispose()
方法会调用 Close()
并执行一些其他的内存释放操作,主要是通过将成员设置为 null 来实现。
而对于 Stream
来说,它们确实是等效的。 Stream.Dispose()
简单地调用了 Close() 方法。
Component
继承的,这个类似乎没有做任何尝试调用Close()
的操作。我在DBConnection
或SqlConnection
中找不到任何与这些通知相关的地方。但是,它确实有一个私有的DisposeMe()
方法,在任何地方都没有被引用。 - Deanna你确实需要调用Dispose()方法!
Dispose()方法是开发者需要主动调用的,垃圾回收器会自动调用Finalize()方法。如果你没有在对象上调用Dispose()方法,那么它们使用的任何非托管资源都不会被释放,直到垃圾回收器遍历并在它们上调用Finalize()方法(而且谁知道什么时候会发生这种情况)。
这种情况被称为不确定性终结,并且是.NET开发者常见的陷阱。如果你正在使用实现IDisposable接口的对象,请务必调用Dispose()方法!
http://www.ondotnet.com/pub/a/oreilly/dotnet/news/programmingCsharp_0801.html?page=last
虽然有很多情况(例如在SqlConnection上)你可以调用Disponse()方法来关闭连接或者关闭文件句柄等,但是除非你计划在不久的将来重新使用该对象,否则调用Dispose()方法几乎总是最好的选择!
using()
语句来调用实现了 IDisposable
接口的类,那么你 应该 调用 Dispose()
方法。如果要调用的类实现了 IDisposable 并且你已经在页面上使用 using()
来包装它的使用,则可以使用 Dispose()
进行释放(别射我,这是双关语)。然而,对于任何显式使用 Open()
的内容,建议使用 Close()
方法。 - René KåbisClose
了一个连接,Postgres 会自动将连接标识符设置为 null
。从那时起,已经设置为 null
的 SQL 连接标识符就无法被 Dispose
。 - ssd正如泰勒在他很好的回答中指出的那样,调用Dispose()
是一个很好的编程实践。这是因为这个方法被认为是“集合”所有需要释放资源的方法,以便没有不必要的开放资源。例如,如果您将一些文本写入文件,但未关闭文件(释放资源),则文件将保持打开状态,直到GC过来并执行您应该执行的操作。
现在,在某些情况下,会有更具体于您处理的类的“终结”方法,例如StreamWriter.Close()
,它覆盖TextWriter.Close()
。实际上,它们通常更适合情况:例如,StreamWriter的Close()
在Dispose()
对象之前刷新流和底层编码器!酷!
然而,浏览MSDN时,您会发现即使是微软也有时会被众多的关闭器和处理器所困扰。例如,在此网页中,有些示例在隐式Dispose()
之前调用Close()
(如果您不了解为什么它是隐式的,请参见using语句),而在其中一个示例中,他们并没有费心这样做。那为什么呢?我也感到困惑。
Close()
可能失败并抛出异常,同时保留资源,而Dispose()
则肯定会释放它们。这就是为什么Dispose()
应该始终保护Close()
调用的原因(对双关语表达歉意)。MyResource r = new MyResource();
try {
r.Write(new Whatever());
r.Close()
finally {
r.Dispose();
}
是的,我想微软在那个例子中犯了一个错误。也许那个时间戳永远不会被刷新到文件中。
明天我会修复我的旧代码。
编辑:对不起Brannon,我不能评论你的答案,但你确定在finally块上调用Close()
是一个好主意吗?我猜那可能会导致整个块出现异常,而这很可能包含重要的清理代码。
回复Brannon的:太好了,只是在真正需要时(例如处理流时-不太了解.NET中的SQL连接)不要忘记调用Close()
。
将类型转换为iDisposable,并在其上调用dispose方法。这将调用配置为实现"iDisposable.Dispose"的任何方法,而不管函数命名如何。
IDisposable.Dispose
,但这并不意味着这就是它的名称。请注意,在vb.net中,一个函数可以绑定到多个接口成员,这些成员的名称与该函数的名称无需相关。 - supercatusing (myObj as IDisposable)
。 - Yousha Aleayoubprivate void CloseConnection(Client client)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.Close();
}
else
{
client.Abort();
}
}
client != null
的检查是不正确/误导的,因为它不能保护所有用法。此外,我不确定代码如何达到“此连接未打开应关闭”的状态。 - user2864740我在使用TransactionScope
时遇到了问题:我连续创建、打开和释放了多个连接,但在完成范围时捕获到了此平台不支持分布式事务
的错误(明显没有分布式事务)。
通过添加Close
方法调用解决了这个问题。大多数答案都说Dispose
和Close
是相同的,但它们似乎并不相同:从源代码中我得出的结论是,Close
方法明确地将连接返回到池中,而我找不到与Dispose
相同的代码。
con.Open() con.Close();
2.con.Open(); // 重用
3.con.Dispose(); // 仅使用一次 con.Open(); // 错误
- Shaiju T