C#使用语句

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方法仍将被调用,但返回语句呢?

或者我应该只使用以下代码:

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;

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

1
无论您在何处返回,Dispose都将被调用。'Using'是您的好朋友! - Chris
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();
        }

从代码中可以看出,无论返回语句如何,resultTable都会被处理。using块只是确保对象在作用域之后被处理。

我认为你的第一段代码看起来没问题,不需要改变。


4

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;

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

1

无论哪种情况,都会释放 DataTable(调用了 .Dispose)。

它被翻译成一个 try/finally,在 finally 中调用 Dispose。正如其名称所示,即使您调用 returnfinally 也会被调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接