Resharper - 可能将Null赋值为非null属性

时间:2016-09-01 15:25:44

标签: c# resharper false-positive

在下面的代码中,Resharper标记了对key的最后两个引用,即使Resharper应该知道key不会为空。

首先,字符串属性检查 Null ,Empty或Whitespace,如果满足任何条件,则跳过该块。扩展方法ToLowerNullSafe()仅在输入为Null时才返回Null - 并且标记为Annotation(第二个代码块)。由于我们已经检查过该属性是非null并且扩展方法被标记为返回非null,我希望Resharper知道key是非空的。

var myObj = new { MyProperty = "some string" };
var myCache = new Dictionary<string, object>();

if (!string.IsNullOrWhiteSpace(myObj.MyProperty))
{
    string key = myObj.MyProperty.ToLowerNullSafe();
    lock (myCache)
    {
        if (!myCache.ContainsKey(key))
        {
            myCache.Add(key, myObj);
        }
    }
}

上面这两行是标记key的地方:

if (!myCache.ContainsKey(key))

myCache.Add(key, myObj);

这是ToLowerNullSafe方法及其注释。

[ContractAnnotation("null => null; notnull => notnull")]
public static string ToLowerNullSafe(this string str)
{
    return string.IsNullOrWhiteSpace(str) ? str : str.ToLower();
}

关于为什么Resharper似乎忽略了注释的任何想法?我该如何解决?

使用:

  • Visual Studio Ultimate 2013 Update 5
  • Resharper 8.2.3
  • 来自Nuget的当前注释(代码和外部)都应用于项目。
  • .Net 4.5.2

修改

myObj.MyProperty 上的冗余空检查 在myObj.MyProperty != null检查之前或之后添加冗余空检查(!string.IsNullOrWhiteSpace)可以清除错误。

if (myObj.MyProperty != null && !string.IsNullOrWhiteSpace(myObj.MyProperty))
{
    string key = myObj.MyProperty.ToLowerNullSafe();
    lock (myCache)
    {
        if (!myCache.ContainsKey(key))
        {
            myCache.Add(key, myObj);
        }
    }
}

key 上的冗余空检查 添加冗余检查,断言或合同假设也可以清除错误。

此处我在为Contract.Assume(key != null);分配值后立即添加了key

if (!string.IsNullOrWhiteSpace(myObj.MyProperty))
{
    string key = myObj.MyProperty.ToLowerNullSafe();
    Contract.Assume(key != null);
    lock (myCache)
    {
        if (!myCache.ContainsKey(key))
        {
            myCache.Add(key, myObj);
        }
    }
}

未调用ToLowerNullSafe 这也清除了错误。但由于ContainsKey方法执行区分大小写的比较,我希望进行不区分大小写的比较,因此可能存在问题。

if (!string.IsNullOrWhiteSpace(myObj.MyProperty))
{
    string key = myObj.MyProperty;
    lock (myCache)
    {
        if (!myCache.ContainsKey(key))
        {
            myCache.Add(key, myObj);
        }
    }
}

调用内置字符串函数ToLower 这也清除了错误。但会使代码库不一致。我们在代码中有许多地方可以预期空值并且必须安全处理,因此为了避免问题,我们在整个代码中应用了自定义...NullSafe扩展方法。我不确定这是否符合“最佳做法”,但这是我们在此项目中所做的。

if (!string.IsNullOrWhiteSpace(myObj.MyProperty))
{
    string key = myObj.MyProperty.ToLower();
    lock (myCache)
    {
        if (!myCache.ContainsKey(key))
        {
            myCache.Add(key, myObj);
        }
    }
}

使用所有工作代码示例,似乎Resharper只是忽略了ToLowerNullSafe扩展方法上的契约注释。但是,在第一个工作示例中,它 识别这些注释,但是通过对对象的属性使用显式和冗余的空值检查。

2 个答案:

答案 0 :(得分:2)

你可以尝试一下吗

[ContractAnnotation("str:null => null; str:notnull=>notnull")]

我在搜索为什么Resharper会这样做并发现这个page,它也可能是Resharper的版本问题?

修改

我已经实现了与您相同的功能,并且完全根据您的代码制作了扩展方法,并且&#34; Key&#34;当我使用注释执行以下操作时。

[ContractAnnotation("null => true; notnull => true")]

希望有所帮助。

答案 1 :(得分:1)

我怀疑这是ReSharper 8中的一个错误(尤其是@ sarel-louw的答案,它在合同中返回一个字符串返回的bool)。我刚刚在ReSharper 2016.2中试过这个,它根本没有标记key个变量 - 不需要ContractAnnotation