7

我真的很想摆脱这个。请看下面的代码:

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;

可能应该使用第二个,但我只需要启发:)。请解释。谢谢。

4

4 回答 4

5

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 块仅确保对象在作用域之后被释放。

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

于 2010-07-06T04:22:36.453 回答
4

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

这是因为,

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

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

.Dispose()呼叫将始终评估。Dispose如果您在using块内返回(在它“真正”返回之前),甚至会评估调用。如果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;
于 2010-07-06T04:20:11.400 回答
1

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

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

于 2010-07-06T04:18:58.723 回答
1

在你的两个例子中,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();
    }
}
于 2010-07-06T04:39:13.523 回答