C# using 语句

发布于 2024-09-08 14:52:00 字数 857 浏览 4 评论 0原文

我真的很想把这件事从我的脑海里赶出去。请看下面的代码:

using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
    List<string> resultsList = new List<string>();
    foreach (DataRow dataRow in resultTable.Rows) {
        resultsList.Add(dataRow[0].ToString());
    }
    return resultsList;
}

数据表是否已处理?有人可以解释一下这是如何转换为 try/catch/finally 块的吗? MSDN 指出,如果发生异常,Dispose 方法仍然会被调用,但是 return 语句呢?

或者我应该使用下面的代码:

List<string> resultsList = new List<string>();
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
    foreach (DataRow dataRow in resultTable.Rows) {
        resultsList.Add(dataRow[0].ToString());
    }
}
return resultsList;

也许应该使用第二个代码,但我只需要启发:)。请解释一下。谢谢。

I really want to get this out of my head. Please see below code:

using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
    List<string> resultsList = new List<string>();
    foreach (DataRow dataRow in resultTable.Rows) {
        resultsList.Add(dataRow[0].ToString());
    }
    return resultsList;
}

Is the datatable disposed? Can someone explain how this is translated to a try/catch/finally block? MSDN states that if an exception occurred, the Dispose method will still be called but what about the return statement?

Or should i just use below code:

List<string> resultsList = new List<string>();
using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) {
    foreach (DataRow dataRow in resultTable.Rows) {
        resultsList.Add(dataRow[0].ToString());
    }
}
return resultsList;

Probably, the second one should be used but I just need enlightenment :). Please explain. Thanks.

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

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

发布评论

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

评论(4

韶华倾负 2024-09-15 14:52:01

Using 不会捕获异常,它只是保证 .Dispose() 调用。

这是因为,

using (ResourceType resource = new ResourceType()) 相当于:

ResourceType resource;
try 
{
     resource = new ResourceType();
     /* The insides of the using block */
}
finally
{
    resource.Dispose();
}

.Dispose() 调用将始终被评估。如果您在 using 块内返回(在“真正”返回之前),则甚至会评估 Dispose 调用。如果抛出异常,Dispose 调用甚至也会被评估。

但是,如果引发异常,该异常仍会阻止后续代码行的求值(.Dispose() 除外,它始终会求值)。

因此,如果发生异常,您的 return 将不会在任何一个语句中返回,但您的 DataTable 仍将被释放。

如果你想保证即使发生错误也能返回,你需要这样做:

List resultsList = new List();
try
{
    using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) 
    {
        foreach (DataRow dataRow in resultTable.Rows) 
        {
            resultsList.Add(dataRow[0].ToString());
        }
    }
}
catch
{
}
return resultsList;

Using does not catch exceptions, it just guarantees the .Dispose() call.

This is because,

using (ResourceType resource = new ResourceType()) is equivalent to:

ResourceType resource;
try 
{
     resource = new ResourceType();
     /* The insides of the using block */
}
finally
{
    resource.Dispose();
}

The .Dispose() call will always be evaluated. The Dispose call is even evaluated if you return within your using block (before it "really" returns). The Dispose call is even evaluated if an exception is thrown.

However, if an exception is thrown, that exception will still prevent subsequent lines of code from being evaluated (with the exception of the .Dispose() which is always evaluated).

As such, if an exception occurs, your return will not return in either of your statements, but your DataTable will still be disposed.

If you want to guarantee a return occurs, even when an error occurs, you want to do something like this:

List resultsList = new List();
try
{
    using (DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable")) 
    {
        foreach (DataRow dataRow in resultTable.Rows) 
        {
            resultsList.Add(dataRow[0].ToString());
        }
    }
}
catch
{
}
return resultsList;
往昔成烟 2024-09-15 14:52:01

在这两种情况下,DataTable 都会被释放(调用.Dispose)。

它被翻译成 try/finally,并在 finally 中调用 Dispose。最后,顾名思义,即使您调用 return 也会调用它。

The DataTable is disposed (.Dispose is called) in both cases.

It's translated into a try/finally, with Dispose being called in the finally. Finally, as the name implies, is called even when you call return.

汐鸠 2024-09-15 14:52:01

在您的两个示例中,都会调用 Dispose 。这是因为 using 语句扩展为 try/finally 块。

请阅读 C# 语言规范(8.13 using 语句)找出各种场景(引用类型、不可空值类型和动态类型)。

由于 DataTable 是引用类型,因此您的第一个示例将扩展为以下内容:

{
    DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
    try {
        List<string> resultsList = new List<string>();
        foreach (DataRow dataRow in resultTable.Rows) {
           resultsList.Add(dataRow[0].ToString());
        }
        return resultsList;
    }
    finally {
        if (resultTable != null) ((IDisposable)resultTable).Dispose();
    }
}

In both your examples, Dispose will be called. This is because the using statement expands to a try/finally block.

Go read the C# Language Specification (8.13 The using statement) to find out the various scenarios (for reference types, non-nullable value types, and dynamic types).

Since DataTable is a reference type, your first sample will expand to the following:

{
    DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
    try {
        List<string> resultsList = new List<string>();
        foreach (DataRow dataRow in resultTable.Rows) {
           resultsList.Add(dataRow[0].ToString());
        }
        return resultsList;
    }
    finally {
        if (resultTable != null) ((IDisposable)resultTable).Dispose();
    }
}
牵你的手,一向走下去 2024-09-15 14:52:00

using 语句只是语法糖,它被翻译成 try/finally 块。从您的代码开始,C# 编译器将如何将 using 块转换为 try/finally 块。

        try
        {
            DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
            List<string> resultsList = new List<string>();
            foreach (DataRow dataRow in resultTable.Rows)
            {
                resultsList.Add(dataRow[0].ToString());
            }
            return resultsList; 
        }
        finally
        {
            resultTable.Dispose();
        }

从代码中可以看出,无论 return 语句如何,resultTable 都会被释放。 using 块仅确保对象在作用域之后被释放。

您的第一个代码对我来说看起来不错,不需要更改。

using statement is just syntactic sugar and it gets translated into try/finally block. Starting with your code, here's how the C# compiler will translate the using block into try/finally block.

        try
        {
            DataTable resultTable = DBUtility.GetSingleDBTableResult(connectionString, "SELECT * FROM MyDBTable");
            List<string> resultsList = new List<string>();
            foreach (DataRow dataRow in resultTable.Rows)
            {
                resultsList.Add(dataRow[0].ToString());
            }
            return resultsList; 
        }
        finally
        {
            resultTable.Dispose();
        }

As you can see from the code, the resultTable gets disposed for sure regardless of the return statement. The using block only makes sure that object gets disposed after the scope.

Your first code looks ok to me and need not be changed.

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