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语句创建的对象。

4

3 回答 3

2

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

if(o == null)

与错误,与您的问题完全相反。

于 2013-03-25T23:43:51.223 回答
1

如果您的代码与编写的代码完全相同,并且 Resharper 真的在抱怨您指出的那一行,那么这是错误的。

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

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

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

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

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

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

于 2013-03-25T23:47:37.410 回答
1

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

没有这是证据。

当然,您正在使用的对象将被释放(这是使用的全部意义),但在块内完成的事情不会受到影响。不过,这是一个新范围,因此您会收到以下代码的警告:

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 的声明)。

于 2013-03-25T23:42:04.650 回答