【问题标题】:Resharper - False positive warning on possible assignment of Null to not-null AttributeResharper - 关于可能将 Null 分配给非空属性的误报警告
【发布时间】:2017-01-09 13:46:00
【问题描述】:

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

首先,检查字符串属性是否存在 Null、Empty 或 Whitespace,如果其中任何一个条件为真,则跳过该块。扩展方法ToLowerNullSafe() 将仅在输入为 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 更新 5
  • Resharper 8.2.3
  • 来自 Nuget 的当前注释(代码和外部)已应用于项目。
  • .Net 4.5.2

编辑

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

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

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

在这里,我在为key 赋值后立即添加了Contract.Assume(key != null);

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 这也清除了错误。但是会使代码库不一致。我们在代码中有很多地方可以预期 null 值并且必须安全处理,因此为了避免出现问题,我们在整个代码中应用了自定义 ...NullSafe 扩展方法。我不确定这是否符合“最佳实践”,但这是我们在这个项目上所做的。

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

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

【问题讨论】:

  • 顺便说一句,使用不区分大小写的字符串比较器而不是区分大小写的默认比较器创建字典可能很有用。那么你根本不需要打电话给ToLower。见this SO question for more
  • @citizenmatt 我必须调查那个建议。

标签: c# resharper false-positive


【解决方案1】:

你可以试试这个

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

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

编辑

我已经实现了与您相同的方法,并完全根据您的代码制作了扩展方法,当我使用 Annotation 执行以下操作时,“键”上的波浪线消失了。

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

希望对您有所帮助。

【讨论】:

  • 由于只有一个参数,包括参数名称是可选的。无论如何,我尝试了您的建议,但没有任何区别。
  • 我不知道是否重要,但扩展方法在解决方案的不同项目中。两个项目具有相同版本的 Resharper、Resharper 代码注释和 Resharper 外部注释。 Resharper 的默认外部注释应该能够识别 string.IsNullOrWhiteSpace 调用,而我对 [ContractAnnotation] 的使用应该在 ToLowerNullSafe 方法上被识别。
  • 我想为什么它是因为 ContainsKey 返回一个布尔值,如果我现在说的正确,注释现在也这样做。现在也在学习这些东西...... :)
【解决方案2】:

我怀疑这是 ReSharper 8 中的一个错误(特别是考虑到@sarel-louw 的答案,它在合同中返回一个布尔值以返回字符串)。我刚刚在 ReSharper 2016.2 中尝试过,它根本没有标记 key 变量 - 不需要 ContractAnnotation

【讨论】:

  • 在管理层决定为升级(或者更好的是,完全订阅)提供资金之前,我一直坚持使用 ReSharper 8.2.3。
猜你喜欢
  • 1970-01-01
  • 2022-01-07
  • 2021-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多