嵌套的 Using 语句有用
本文关键字:有用 语句 Using 嵌套 | 更新日期: 2023-09-27 18:34:08
关于资源密集型操作(例如打开数据库连接(的最佳实践的共识似乎是使用Using
块,因为Using
块"保证了资源的处置......即使在未处理的异常的情况下。
以下是我找到的大多数示例的编写方式:
Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
Using connection As New SqlConnection(connectionString)
Dim command As New SqlCommand(sql, connection)
command.Connection.Open()
command.ExecuteNonQuery()
End Using
End Sub
但是嵌套Using
块是允许的,我偶尔(但很少(看到上面写成:
Sub ExecuteCommand(ByVal sql As String, ByVal connectionString As String)
Using connection As New SqlConnection(connectionString)
Using command As New SqlCommand(sql, connection)
command.Connection.Open()
command.ExecuteNonQuery()
End Using
End Using
End Sub
我的问题:多个嵌套Using
块有什么好处吗?还是单个 Using 块已经保证它包含的所有资源都将被释放?
(注意:我的代码是 VB.NET 的,但同样的问题适用于 C#。
使用块"保证资源的处置...即使在未处理的异常的情况下。
对这个"保证"持保留态度。许多事情会阻止资源的处置。如果使用块包含无限循环怎么办?或者块抛出异常,堆栈上较高的恶意异常过滤器进入无限循环,并且永远不会将控制权返回给与 using 语句关联的 finally 块? 或者块调用环境.失败快速? 有很多很多事情可以阻止处置运行。 永远不要编写依赖于处置的正确性的程序。 处置是为了礼貌,将稀缺的资源归还给池子供他人使用。
此外,让我确保这一点是明确的:真正未经处理的异常是 C# 中实现定义的行为。using
块的 finally 子句用于处理异常在 using 块内抛出然后在其他地方处理的情况,而不是处理异常在块内抛出但从未处理的情况。如果发生这种情况,那么完全由实施来确定会发生什么;C# 语言对引发从未处理的异常的程序的行为总共做出零承诺。资源可能会被释放。他们可能不会。你身处一栋即将被意外拆除的建筑物中;你真的想花时间洗碗并把它们整齐地收起来吗?
多个嵌套的 Using 块有什么好处吗?
是的。
单个 Using 块是否已经保证它包含的所有资源都将被释放?
不。仅清理 using 语句实际提到的资源。这就是你嵌套它们的原因。
在某些情况下,从技术上讲,您不必这样做,因为内部负责释放与外部相同的资源。但是使用块嵌套并没有什么坏处,它让读者非常清楚发生了什么。 此处的最佳做法是为要清理的每个资源设置一个 using 语句。
嵌套的using
块绝对有用:单个块将仅在其自己的变量上调用Dispose
,而不会在同一块内可能打开的其他变量上调用。这就是为什么您要在程序中的某个定义点清理的每个变量(应该是实现IDisposable
类型的每个变量(都需要自己的using
块。
Using
语句将释放在Using
行中声明的变量。
它对块中其他位置声明的变量没有影响。
应始终对每个一次性变量使用 Using
语句。
所有其他答案都是正确的。我还要补充一点。
如果对象类型相同,C# 编译器提供了一种在单个 using
语句内联中使用多个对象的方法(语法糖(。
C# 版本
using (MemoryStream ms1 = new MemoryStream(), ms2 = new MemoryStream())
{
}
Vb.Net 版本
Using ms1 = New MemoryStream(), ms2 = New MemoryStream()
End Using
这将处理两个MemoryStream
嵌套using
语句非常有用。但是,许多程序员并不认为SqlCommand
对象需要进行资源清理。即,资源是连接,而不是命令。
添加
SqlCommand 没有 Close(( 方法,所以即使 SqlCommand 有一个 Dispose(( 方法,缺少 Close(( 方法表明真的"没有什么可以关闭/释放的"。一次性实例最终将始终被释放。如果不挖掘来源,很难找到权威的东西,但是当在本文中被问及MS人员确切地处理了什么时,他说"实际上不是很多......"并继续为 SqlCommand(( 建议使用 USING 子句,所以我正确地回答了这个问题,但最初避免了它背后的模糊性。