【问题标题】:ReSharper ContractAnnotation for Null Check + Out Variable giving counter-intuitive resultsReSharper ContractAnnotation for Null Check + Out Variable 给出反直觉的结果
【发布时间】:2021-08-20 08:54:46
【问题描述】:

我有一个相对简单的扩展方法,叫做 TryGetFirst

public static bool TryGetFirst<T>(this IList<T> list, out T value)
{
    if (list == null || list.Count == 0)
    {
        value = default;
        return false;
    }

    value = list[0];
    return true;
}

它同时做几件事情。它 null 检查列表,检查列表是否为空,如果不是,则返回第一个元素。有点像 Linq 的 FirstOrDefault 但有一个内置的空检查。没什么太花哨的。

我正在寻找正确的 ContractAnnotation 语法来将以下事实传达给 ReSharper,但我似乎无法将它们全部确定下来。

  1. 如果列表为 null,则始终返回 false
  2. 如果返回值为真,则列表不为空
  3. 如果返回值为false,则值为null

鉴于以下代码,我期望以下 ReSharper 提示,至少在 Rider 的悲观值分析模式下

if (StringExtensions.TryGetFirst<object>(null, out object value) { ... } // Expression is Always False

if (_possiblyNullList.TryGetFirst<object>(out object value)
{
    _possiblyNullList.DoSomething(); // No Warning
    value.DoSomething(); // Possible NullReferenceException
}
else
{
    _possiblyNullList.DoSomething(); //Possible NullReferenceException
    if (value == null) { ... } // Expression is Always True
}

起初我尝试了[ContractAnnotation("list:null =&gt; false; =&gt; false, value:null")],但由于某种原因,ReSharper 解释为所有代码路径总是返回 false,因此无法访问 if { ... } 的内容。

接下来我尝试了[ContractAnnotation("list:null =&gt; false; =&gt; false, value:null; =&gt; true")],因为我认为在最后添加真实案例会告知 ReSharper 真实结果是可能的。这稍微好一些,但是 if 块中的 _possiblyNullList.DoSomething(); 被标记为可能的 NullReference,StringExtensions.TryGetFirst&lt;object&gt;(null, ... 不再被标记为 Always False。

我最接近我的目标的是[ContractAnnotation("=&gt; true, list:notnull, value:canbenull; =&gt; false, list:canbenull, value:null")],它处理除了StringExtensions.TryGetFirst&lt;object&gt;(null, ... 之外的所有情况,它没有被标记为Always False。我尝试添加回list:null =&gt; false 行,但没有任何区别。我也觉得这种语法比看起来需要的要冗长得多,但如果它是准确的,我愿意接受它。

我觉得我的排列组合已经用完了。这只是属性不支持的情况,还是我遗漏了一些明显的东西?

【问题讨论】:

  • 看来[ContractAnnotation("list:null =&gt; false, value:null")] 可以解决问题。至少有指定的要求。
  • @GuruStron 另一个非常接近的,但至少据我所知,它不会像在 else 块中那样标记if (value == null) { ... }。存在list不为null但返回值为false的情况,因此out值为null。

标签: c# resharper jetbrains-ide rider


【解决方案1】:

试试这个: list:null =&gt; false,value:null;list:notnull=&gt;false,value:null;list:notnull=&gt;true,value:canbenull

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-20
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-30
    • 2018-07-28
    相关资源
    最近更新 更多