试着更好地理解’使用’语句

我已经阅读了几篇关于using语句的文章,试图了解何时应该使用它。 这听起来像大多数人认为它应该尽可能多地使用,因为它可以保证处理未使用的物体。

问题是所有的例子总是显示如下:

using (SqlCommand scmFetch = new SqlCommand()) { // code } 

这是有道理的,但它只是一小段代码。 在数据库上执行查询时应该怎么做? 所有步骤是什么? 它看起来像这样:

 string sQuery = @" SELECT [ID], [Description] FROM [Zones] ORDER BY [Description] "; DataTable dtZones = new DataTable("Zones"); using (SqlConnection scnFetchZones = new SqlConnection()) { scnFetchZones.ConnectionString = __sConnectionString; scnFetchZones.Open(); using (SqlCommand scmdFetchZones = new SqlCommand()) { scmdFetchZones.Connection = scnFetchZones; scmdFetchZones.CommandText = sQuery; using (SqlDataAdapter sdaFetch = new SqlDataAdapter()) { sdaFetch.SelectCommand = scmdFetchZones; sdaFetch.Fill(dtZones); } } if (scnFetchZones.State == ConnectionState.Open) scnFetchZones.Close(); } 

我想知道的是:
•是否可以使用4,5,10个嵌套的using语句来确保处理所有对象?
•我在什么时候做错了什么,我应该考虑修改吗?
•如果由于嵌套的using语句太多需要修订,我有哪些选择?

您最终可能会遇到强大的层次结构,但您的代码应该非常高效,对吧? 或者你应该只在一个using语句中放置SqlDataAdapter对象,它会以某种方式确保所有其他对象也被处理掉?

感谢名单。

拥有许多嵌套的using语句是完全有效的:

 using(A a = new A()) using(B b = new B()) { a.SomeMethod(b); } 

如果你使用你使用的每个IDisposable,你永远不会错。 您使用的嵌套使用块数没有限制。

using语句是C#的语法糖。

所以下面的代码:

 using(var someDisposableObject = new someDisposableObject()) { // Do Something } 

实际看起来像:

 var someDisposableObject = new someDisposableObject(); try { // Do Something } finally { if (someDisposableObject != null) { ((IDisposable) someDisposableObject).Dispose(); } } 

看看这篇文章: http : //msdn.microsoft.com/en-us/library/yh598w02.aspx

深度没有限制,所以这不是一个问题。 您应该validationusing的对象是否实现了IDisposable。 并且处理的对象不会处理与其连接的所有对象,只会处理它创建的对象。

所以,你在什么时候做错了:没有限制,但通常它相当浅,你创建对象,做一个任务,然后对象被处理掉。 如果你这么做,我会看看设计。 我认为你很难做到这一点而不是几层深。

至于您重新设计的选项,这实际上取决于您正在做什么,但您可能会将同一个对象用于多个任务。 最有可能的是,您最终会将任务分解为一个函数(传入所需的任何周围对象)。

•是否可以使用4,5,10个嵌套的using语句来确保处理所有对象?

回复: 您不能限制使用嵌套的“使用块”。

•我在什么时候做错了什么,我应该考虑修改吗?

回复: 如果你有很多嵌套的“使用块”。 请尝试如下。

  using (var con = new SqlConnection(connStr)) using (var cmd = new SqlCommand(queryStry)) using (var rs = cmd.ExecuteReader()) { while (rs.Read()) { //Code. } } 

就个人而言,我已经多次使用至少3层(连接,命令,其他),我看到它完全没有问题,但正如你已经暗示的那样,最终会出现可读性问题。 与其他嵌套构造一样,您可能需要在可维护性之间平衡效率。 也就是说,你不一定要牺牲效率,但通常“不止一种方法可以给猫皮肤”。

也就是说,您将很难生成10个嵌套层!

恕我直言,你需要问自己的是:有什么选择? 尝试/最后阻止? 它们更具可读性吗? 更难维护? 几乎在所有情况下,答案都是“不”。

所以使用。 这是C#对C ++的RAII模式最接近的事情,它一切都很好:-)

有一段时间我可以想到你不想在连接上使用’using’的地方将是ClassFactories用于连接对象,例如DataReaders,例如考虑案例

 private IDataReader CreateReader(string queryString, string connectionString) { SqlConnection connection = new SqlConnection(connectionString); SqlCommand command = new SqlCommand(queryString, connection); connection.Open(); return command.ExecuteReader(CommandBehavior.CloseConnection); // Don't close connection } 

(从MSDN修改 – MSDN上的示例只是简单的愚蠢)

另一个原因是WCF ServiceReference’客户端’ – 如果通道出现故障,’使用’则会隐藏实际的exception。 但这只是一个有缺陷的实施恕我直言。