我遇到代码合同和linq的问题。我设法将问题缩小到以下代码示例。现在我被卡住了。
public void SomeMethod()
{
var list = new List<Question>();
if (list.Take(5) == null) { }
// resharper hints that condition can never be true
if (list.ForPerson(12) == null) { }
// resharper does not hint that condition can never be true
}
public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
if(source == null) throw new ArgumentNullException();
return from q in source
where q.PersonId == personId
select q;
}
我的linq链有什么问题?在分析ForPerson电话时,为什么不重新收起'抱怨'?
编辑:ForPerson方法的返回类型已从字符串更改为IQueryable,我的意思是。 (我的坏)
答案 0 :(得分:4)
重新整形器是正确的,Take
或Skip
的结果永远不会为空 - 如果没有项目,则结果是没有元素的IEnumerable<Question>
。我想你应该做你想做的事情,你应该检查Any
。
var query = list.Take(5);
if (!query.Any())
{
// Code here executes only if there were no items in the list.
}
但这个警告如何运作? Resharper无法知道该方法永远不会仅仅查看方法定义而返回null,并且我认为它不会对方法体进行反向工程以确定它永远不会返回null。因此我假设它已经特别硬编码,并且规则指定.NET方法Skip and Take不返回null。
当您编写自己的自定义方法时,Reflector可以从界面中对您的方法行为做出假设,但是您的界面允许它返回null。因此它不会发出任何警告。如果它分析了方法体,那么它可以看到null是不可能的并且能够发出警告。但分析代码以确定其可能的行为是一项非常困难的任务,我怀疑Red Gate是否愿意花钱解决这个问题,因为他们可以在其他地方以更低的开发成本添加更多有用的功能。
确定布尔表达式是否可以返回 true 被称为Boolean satisfiability problem并且是NP难题。
您希望Resharper确定一般方法体是否可以返回 null 。这是上述NP难问题的推广。在100%的情况下,任何工具都不可能正确地执行此操作。
答案 1 :(得分:0)
if(source == null) throw new ArgumentNullException();
那不是代码合同方式,你的意思是:
Contract.Require(source != null);