根据MSDN,如果嵌套内部using语句的IDisposable资源包含外部using语句的资源,则嵌套资源的Dispose方法将释放所包含的资源。
MSDN(http://msdn.microsoft.com/en-us/library/ms182334.aspx)=>
示例嵌套using语句(在Visual Basic中使用)可能导致违反CA2202警告。如果嵌套的内部using语句的IDisposable资源包含外部using语句的资源,则嵌套资源的Dispose方法将释放所包含的资源。发生这种情况时,外部using语句的Dispose方法将尝试第二次处置其资源。在以下示例中,在包含流对象的StreamWriter对象的Dispose方法中,在外部using语句的末尾释放在外部using语句中创建的Stream对象。在外部using语句的末尾,第二次释放流对象。第二个版本违反了CA2202。
但是,如果我尝试这段代码,该代码仍然有效,并返回插入表中的数字计数。这与MSDN解释矛盾。我希望代码在cmd.ExecuteScalar()调用时崩溃,因为conn变量位于第一个内部using语句之后。为什么这仍然有效,为什么第一次使用完内部后就不会处理conn变量?
static void Main(string[] args)
{
var numbers= DoItGetIt();
}
private static int DoItGetIt()
{
using (var conn = new SqlConnection("Data Source=BestmixSql;Initial Catalog=Test;Integrated Security=True"))
{
conn.Open();
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = "INSERT INTO [Test].[dbo].[Tabel] VALUES (666)";
cmd.ExecuteNonQuery();
}
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandText = "SELECT COUNT(*) FROM [Test].[dbo].[Tabel]";
var count = cmd.ExecuteScalar();
return Convert.ToInt32(count);
}
}
}
您正在谈论的MSDN示例是专门针对内部对象占据外部对象的情况的;例如,StreamWriter
可以为承担责任Stream
。在那种情况下,放置内部对象也会导致放置外部对象-但这在通常情况下是不正确的。
特别是,命令不承担处置连接的责任。有趣的是,数据读取器可以承担责任,但只能通过可选标志来承担责任。
许多这样的对象提供标志,以使调用者确定内部对象是否应承担处置外部对象的责任。例如,StreamWriter
现在还提供了带有bool leaveOpen
参数的构造函数重载。如果通过as true
,StreamWriter
则不会级联Dispose()
。
这是所有的内部对象的实现细节,当它被专门编写做到这一点。这不是该using
模式的默认行为。
旁注:我会说MSDN在这里根本是错误的。的正确实施是有两个第一样品using
。第二个示例是非直觉的,并且容易实现错误。不要使用它。如果需要,leaveOpen
make的使用是明确的,但坦率地说,如果您无论如何都要使用它,通常无需使用它就可以正常工作。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句