如何避免Linq链接返回null?

时间:2010-06-19 10:09:06

标签: linq resharper code-contracts

我遇到代码合同和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,我的意思是。 (我的坏)

2 个答案:

答案 0 :(得分:4)

重新整形器是正确的,TakeSkip的结果永远不会为空 - 如果没有项目,则结果是没有元素的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);