[英]c# using statement with double IDisposable
我有以下using语句using
:
using (var reader = data.CreateCommand(sql).ExecuteDataReader())
在这种情况下, data
是内部保存SqlConnection
某个对象。 CreateCommand(sql)
函数返回SqlCommand
而ExecuteDataReader
返回SqlDataReader
。 由于SqlCommand
和SqlDataReader
都是IDisposable
,因此使用using
语句会将它们都丢弃吗?
现在,我已经这样完成了:
using (var cmd = data.CreateCommand(sql))
using (var reader = cmd.ExecuteDataReader())
但是我想知道是否可以如上所述将它们组合在一起?
同意Matthew Watson的评论。 您需要同时usings
usestatemets。 这是带有其他推理的相关问题。 SqlConnection SqlCommand SqlDataReader IDisposable
“如果有可能将它们组合在一起” -两种using
都很好,因为两者都需要处理。
您可以通过提取为方法来组合它们:
void RunWithReader(string sql, Action<SQLDataReader> action)
{
using (var cmd = data.CreateCommand(sql))
using (var reader = cmd.ExecuteDataReader())
action(reader);
}
然后你可以使用lambda
RunWithReader("whatever command", reader =>
{
... // while(reader.Read() { ... } - this could also be extracted
});
内部IDisposable
( IDbCommand
)呈现代码的方式没有被处理。
您有两种选择:
你可以把它们都放在一个using
这样的:
using (IDisposable cmd = data.CreateCommand(), reader = ((IDbCommand)cmd).ExecuteReader())
{
// code here
}
但这相当麻烦。 另一个选项是using
语句嵌套的:
using (var cmd = data.CreateCommand())
{
using (var reader = cmd.ExecuteReader())
{
// code here
}
}
除此之外,您可能会变得有些复杂,并编写扩展方法来帮助您进行某种清理。
public static class Ex
{
public static void Using<T, R>(this T obj, Func<T, R> create, Action<T, R> use) where R : IDisposable
{
using (var d = create(obj))
{
use(obj, d);
}
}
}
然后,您可以执行以下操作:
data.Using(d => d.CreateCommand(), (d, c) => c.Using(c2 => c2.ExecuteReader(), (c3, r) =>
{
// code here
}));
但这可能不是很大的改进。
您应该
Dispose
实现IDisposable
每个类 。
但是,您的问题是专门处理所有资源都相关的场景,如果我理解正确,那么垃圾收集器将自动为您处理这些资源。
Finalize()
方法(“析构函数”或“终结器”)
Finalize()
方法可确保在应用程序不再引用实例时处理资源。
与 Dispose()
方法 一起使用
Dispose()
方法将“释放该组件使用的所有资源”。 这意味着该代码块(取自MSDN的ExecuteReader方法示例 )将正确处理其使用的所有组件...
using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(queryString, connection); SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { // ... } }
在这种情况下,处置
SqlConnection
,它将正确释放该组件使用的所有资源 。 意思是:
SqlCommand
SqlDataReader
** 注意:这一直是我的理解 ...
将上面的代码重构为以下代码:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(queryString, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
手动处理每个资源的主要优点是可以提高性能,因为我们没有处理
Finalize
方法(与Dispose()
相比,这种方法相对更昂贵Dispose()
。
但是,这并不意味着您想全部Dispose()
,因为在某些情况下, Finalize()
方法是更好的选择。
假设到目前为止我仍然处在良好状态,并且我对垃圾收集器的行为的理解是正确的。
我认为SqlCommand
( 在此处有完整的代码参考)也将处置SqlReader
,这意味着您可以摆脱:
using (SqlCommand command = new SqlCommand(queryString, connection))
{
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// ...
}
}
在您的情况下,将转换为:
using (var cmd = data.CreateCommand(sql)) { var reader = cmd.ExecuteDataReader(); // ... }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.