为什么resharper仍然为此代码提供空引用警告

时间:2011-11-08 16:49:46

标签: c# asp.net resharper

此方法是aspx GridView控件中OnRowCommand的事件处理程序。 Resharper警告gvUnitsgvUnit.DataKeysgvUnits.DataKeys[index]可以为null,并建议在第二个if语句中添加检查。添加后,它会创建一个警告gvUnits.DataKeys != null始终为真。既没有按照建议添加这些检查,也没有手动添加断言抑制了警告。

我不明白这里发生了什么:gvUnits是不是挥发性的,如果是这样,为什么,它是resharper 5.1中的一个错误,还是其他的东西?

protected void GvUnitsRowCommand(object sender, System.Web.UI.WebControls.GridViewCommandEventArgs e)
{
    if (e.CommandName == "EditUnit")
    {
        int index = int.Parse(e.CommandArgument.ToString());
        if (gvUnits != null && gvUnits.DataKeys != null && gvUnits.DataKeys.Count > index)
        {
            Debug.Assert(gvUnits != null);
            Debug.Assert(gvUnits.DataKeys != null);
            Debug.Assert(gvUnits.DataKeys[index] != null);

            int unitID = (int)gvUnits.DataKeys[index].Value;
            //do stuff with unitID
        }
    }
}

2 个答案:

答案 0 :(得分:6)

假设DataKeys是一个属性,那么gvUnits.DataKeys本质上是一个方法调用(调用一个getter。)因此,如果你调用它两次,则无法保证它不会返回null在第二个电话。同样,如果DataKeys[index]是索引器调用(不是数组访问),那么这也是一个方法调用,如上所述,它可以在第二次调用时返回null。提供保证断言的唯一方法是将每个调用的结果存储在局部变量中,然后断言本地值不为空。由于本地值不能在用法之间改变,ReSharper知道它是安全的。

这是你在没有意识到的情况下进行隐式假设的情况之一(属性的返回值不会在调用之间发生变化。)如果你愿意,可以用注释来抑制警告,而不是而不是为断言创建本地副本,这基本上将假设推送到属性实现者(以保证连续调用之间的不可变性。)

答案 1 :(得分:1)

检查一下: 如果int.Parse输入尝试使用(int)

,则nullConvert.ToInt32将失败
if (e.CommandName == "EditUnit")
{
    int index = Convert.ToInt32(e.CommandArgument);
    DataKey key = GridView1.DataKeys[index];
    if (key!=null)
    {
        int id = Convert.ToInt32(key.Value);
    }
}