确保 IEnumerable 不为空的合同

Contract that ensures the IEnumerable is not empty

给定的代码

static public int Q()
{
    return Enumerable.Range(0, 100)
        .Select(i => i)
        .First();
}

发出以下警告:

warning : CodeContracts: requires unproven: Any(source)

如果我删除 .Select() 子句,它就会消失。

但我不清楚我到底需要什么 .Ensure 才能满足 cccheck

由于这解决了问题并且仍然不像人们最初想象的那么难看,我将其作为答案发布(如果有人有更好的想法,我愿意接受您的建议):

static public int Q()
{
    var e = Enumerable.Range(0, 100)
        .Select(i => i);

    Contract.Assume(e.Any());
    return e.First();
}

所以我不必拆分整个表达式,而是拆分静态分析器害怕的部分,对于那部分我可以保证它是 "all fine, trust me, I know what I'm doing"。

备注:

出于某种原因

Contract.Assert(e.Count() > 0);

Contract.Assert(e.Any());

工作。

重要:正如其他人提到的,这可能并不适合所有情况,因为额外的 e.Any() 调用会具体化集合,这在某些情况(例如:当它是来自第 3 方来源的 LINQ 时)。

你能用这段代码避免警告吗?

var res = Enumerable.Range(0, 100).Select(i => i).Take(1); //execute one query with TOP1 and store in memory
Contract.Assume(res.Any()); //or res.Count() > 0 //query already in memory
return res.First(); //query already in memory