试图理解“使用”声明更好

发布于 2024-12-15 17:29:24 字数 1260 浏览 0 评论 0原文

我读过几篇关于 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 语句太多而需要进行修改,我有什么选择?

您最终可能会得到一个强大的层次结构,但您的代码应该非常高效,对吗?或者您是否应该只将 SqlDataAdapter 对象放入 using 语句中,并且它会以某种方式确保所有其他对象也被释放?

谢谢。

I have read a couple of articles about the using statement to try and understand when it should be used. It sound like most people reckon it should be used as much as possible as it guarantees disposal of unused objects.

Problem is that all the examples always show something like this:

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

That makes sense, but it's such a small piece of code. What should I do when executing a query on a database? What are all the steps? Will it look something like this:

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();
}

What I want to know is:
• Is it okay to have 4, 5, 10 nested using statements to ensure all objects are disposed?
• At what point am I doing something wrong and should I consider revision?
• If revision is required due to too many nested using statements, what are my options?

You might end up with a formidable hierarchy, but your code should be quite efficient, right? Or should you only put, for instance, the SqlDataAdapter object in a using statement and it will somehow ensure that all the other objects get disposed as well?

Thanx.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

别把无礼当个性 2024-12-22 17:29:24

就我个人而言,我至少多次使用过 3 层(连接层、命令层、其他层),我认为它绝对没有问题,但正如你已经暗示的那样,最终会出现可读性问题。与其他嵌套构造一样,您可能需要平衡效率和可维护性。也就是说,你不一定要牺牲效率,但往往“剥猫皮的方法不止一种”。

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

Personally, I have used at least 3 layers (Connection, Command, Other) a number of times and I see absolutely no problem with it, but as you have already hinted at, eventually there will be a problem a readability. As with other nested constructs, you may need to balance efficiency with maintainability. That is, you don't need to necessarily sacrifice efficiency, but there is often 'more than one way to skin a cat'.

That said, you would be hard-pushed to generate 10 nested layers!

寒江雪… 2024-12-22 17:29:24

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

所以使用using。这是 C# 与 C++ 的 RAII 模式最接近的东西,而且一切都很好:-)

IMHO, what you need to ask yourself is: What are the alternatives? Try/finally blocks? Are they more readable? More maintainable? In almost all cases, the answer is going to be "no".

So use using. It's the closest thing C# has to C++'s RAII pattern and it's all good :-)

此刻的回忆 2024-12-22 17:29:24

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

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

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

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

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

• Is it okay to have 4, 5, 10 nested using statements to ensure all objects are disposed?

Reply: You can not limit of using nested "using blocks ".

• At what point am I doing something wrong and should I consider revision?

Reply: If you have many nested "using blocks". Please try as below.

        using (var con = new SqlConnection(connStr))
        using (var cmd = new SqlCommand(queryStry))
        using (var rs = cmd.ExecuteReader())
        {
            while (rs.Read())
            {
                //Code.
            }
        }
暮色兮凉城 2024-12-22 17:29:24

深度没有限制,所以不用担心。您应该验证使用的对象是否实现了 IDisposable。被处置的对象不会处置与其连接的所有对象,而只会处置其创建的对象。

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

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

There's no limit on the depth, so that's not a concern. You should verify that the object of the using implements IDisposable. And an object being disposed doesn't dispose of all objects connected to it, just those it creates.

So, at what point are you doing wrong: there's no limit, but generally its fairly shallow, you create the object, do a task, then the object is disposed. If you're doing it very deeply, I'd look at the design. I think you'd be hard pressed to do it more than few layers deep.

As for your options for a redesign, that really depends upon what you are doing, but you might use the same object for multiple tasks. Most likely you will end up breaking the task down into a function (passing in any surrounding objects that are needed).

柒七 2024-12-22 17:29:24

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

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

It is perfectly valid to have many nested using statements:

using(A a = new A())
using(B b = new B())
{
   a.SomeMethod(b);
}
呆橘 2024-12-22 17:29:24

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

You would never be wrong if you use using for every IDisposable that you use. There is no limit of how many nested using blocks you use.

药祭#氼 2024-12-22 17:29:24

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

Using statement is syntax sugar of C#.

So the following code:

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

actualy looks like:

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

Look at this article: http://msdn.microsoft.com/en-us/library/yh598w02.aspx

丘比特射中我 2024-12-22 17:29:24

有一次我能想到你不会 想要在连接上使用“using”将在用于连接对象(例如 DataReaders)的 ClassFactories 上,例如考虑这种情况

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 服务参考“客户端” - 如果通道出现故障,“使用”然后隐藏实际的异常。但这只是一个有缺陷的实现恕我直言。

One time I can think of where you wouldn't want to use 'using' on connections would be on ClassFactories for connected objects such as DataReaders, e.g. consider the case

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
}

(Modified from MSDN - The example on MSDN is just plain stupid)

Another reason is on WCF ServiceReference 'clients' - if the channel becomes faulted, 'using' then hides the actual exception. But this is just a buggy implementation IMHO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文