试图更好地理解'使用'声明

时间:2011-11-15 08:01:43

标签: c# using-statement

我已阅读了几篇关于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语句来确保处理所有对象? •我在什么时候做错了什么,我应该考虑修改吗? •如果由于嵌套使用语句太多而需要修订 ,我有哪些选择?

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

感谢名单。

8 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

使用语句是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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

•是否可以使用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.
            }
        }

答案 5 :(得分:0)

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

那就是说,你很难生成10个嵌套层!

答案 6 :(得分:0)

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

因此请使用using。它是C#与C ++ RAII模式最接近的东西,它一切都很好: - )

答案 7 :(得分:0)

有一段时间我可以想到wouldn't想要在连接上使用'使用'的位置将在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 'clients' - 如果频道出现故障,'使用'则会隐藏实际的异常。但这只是一个有缺陷的实施恕我直言。