如何解决用于 Null Check + Out 变量的 ReSharper ContractAnnotation 给出了违反直觉的结果
我有一个相对简单的扩展方法,叫做 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;
}
它同时做几件事。它为空检查列表,检查列表是否为空,如果不是,则返回第一个元素。有点像 Linq 的 FirstOrDefault 但有一个内置的空检查。没什么太花哨的。
我正在寻找正确的 ContractAnnotation 语法来向 ReSharper 传达以下事实,但我似乎无法将它们全部确定下来。
- 如果列表为空,总是返回false
- 如果返回值为真,则列表不为空
- 如果返回值为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 => false; => false,value:null")]
,但出于某种原因,ReSharper 将其解释为所有代码路径始终返回 false,因此 if { ... }
的内容无法访问。
接下来我尝试了 [ContractAnnotation("list:null => false; => false,value:null; => true")]
,因为我认为在最后添加真实案例会通知 ReSharper 真实结果是可能的。这稍微好一点,但是 if 块中的 _possiblyNullList.DoSomething();
被标记为可能的 NullReference,而 StringExtensions.TryGetFirst<object>(null,...
不再被标记为 Always False。
最接近我的目标的是 [ContractAnnotation("=> true,list:notnull,value:canbenull; => false,list:canbenull,value:null")]
,它处理所有情况,除了 StringExtensions.TryGetFirst<object>(null,...
没有被标记为 Always False。我尝试重新添加 list:null => false
行,但没有任何区别。我也觉得这种语法比看起来需要的要冗长得多,但如果它准确,我愿意接受它。
我觉得我已经用完了可以尝试的排列。这只是属性不支持的情况还是我遗漏了一些明显的东西?
解决方法
试试这个:
list:null => false,value:null;list:notnull=>false,value:null;list:notnull=>true,value:canbenull
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。