初始化“使用”块中的对象是否将其置于块外?

时间:2013-03-25 23:39:25

标签: c# c#-4.0

我有一些看起来像这样的代码:

Object o;
using (SqlConnection sql = GetSqlConnection) {
    using (SqlCommand sqlCommand = GetSqlCommand()) {
        using (Datareader dr = GetDataReader()) {
            o = new Object();
            while (dr.read()) {
                //do something
            }
        }
        if (o == null) // RESHARPER SAYS THAT THIS WILL ALWAYS BE TRUE
            //do something
    }
}

我检查o == null的地方,ReSharper说这个命令永远都是真的。我不明白这种行为;对using块中初始化的所有对象进行处理,或仅使用using语句创建的对象。

3 个答案:

答案 0 :(得分:2)

当关闭using块时,它将在该对象上调用Dispose(),这取决于IDisposable的实现,可以将对象设置为null。但是,在您的情况下,“o”不是IDisposable或在使用块中,并且我愿意相信ReSharper在这种情况下有一个错误,因为当我在安装中有完全相同的代码时,它会提示我替换

if(o == null)

错误,恰恰与您的问题相反。

答案 1 :(得分:1)

  

初始化“using”块中的对象是否将其置于外部   块?

即可。 Here is proof.

您使用的对象当然会被处理(这是整个使用的重点),但是在块内完成的事情不会受到影响。不过,这是一个新的范围,因此您可以通过代码获得警告:

Object o;
using (SqlConnection sql = GetSqlConnection) {
    using (SqlCommand sqlCommand = GetSqlCommand()) {
        using (Datareader dr = GetDataReader()) {
            Object o = new Object();
            while (dr.read()) {
                //do something
            }
        }
        if (o == null) // RESHARPER SAYS THAT THIS WILL ALWAYS BE TRUE
            //do something
    }
}

(注意内部范围内第二个对象o的声明)。

答案 2 :(得分:1)

如果您的代码完全按照书面形式编写,并且Resharper真的抱怨您指定的行,那么这是错误的。

事实上,ReSharper完全倒退了:比较是多余的,因为它永远是真的。您立即将o设置为new Object(),因此它永远不会是null。除了您在开始语句中输入的变量之外,using块对变量的值没有影响。在离开using块时,通过在其上调用IDisposable.Dispose来处理该实例,并且它超出范围。

但是,我确实想纠正您似乎遇到的一个巨大误解: 处置对象时不会将其设置为null 。以下代码 在尝试关闭已经处置的对象时仍然会崩溃:

var conn = new SqlConnection(GetConnectionString());
conn.Open();
conn.Dispose();

if (conn != null)
{
  conn.Close();
}

“被处置”是适用于对象实例的条件;这意味着他们的资源已被清理干净,无法再安全使用。 “为空”是适用于变量的条件;这意味着他们不会引用他们定义类型的任何实例,无论是处置还是其他。

using关键字和IDisposable接口用于管理对象实例的is-dispos-of状态。它们对程序中变量的is-a-null值状态没有影响。