代码契约:要求IEnumerable为非空

时间:2010-12-21 21:09:48

标签: c# c#-4.0 code-contracts

我有以下代码:

public static IEnumerable<long> GetAllCombinations(IEnumerable<long> elements)
{
    Contract.Requires(elements != null);
    return GetAllCombinations(elements.ToList(), 0);
}

静态分析现在告诉我添加另一个先决条件:

  

CodeContracts:建议的前提条件:   Contract.Requires(最大值> = 0)

我不明白这个建议,因为

a)如果我已经确保元素不为空,我为什么要检查其计数是大于还是 等于 为零?我的意思是,传递一个非空值已经意味着它包含至少零元素?

b)我应该如何检查IEnumerable的计数(或建议的最大值)?我看到的唯一方法是将elements.ToList()分配给一个额外的变量并检查该变量。但是,如果我不想从IEnumerable中列出一个列表呢?

让我困惑。

编辑:

我知道IEnumerable<T>的所有扩展方法,并且非常了解.Any().Count()等。

让我感到困惑的是来自静态分析仪的信息。任何人都可以解释为什么它陈述Contract.Requires(maximum >= 0)

它甚至意味着我认为它意味着什么(检查元素的数量&gt; = 0)?

并且,如评论中所述,为什么静态分析器仍对Contract.Requires(elements.Any());不满意?

3 个答案:

答案 0 :(得分:1)

我不确定为什么静态分析会建议检查集合的数量。如果传递了一个空集合,则不会执行评估它的代码(即foreach语句),该语句应为o.k.也许这与签名类型的集合的Count有关?您可能希望尝试使用Contracts.Assume(elements.Any())或类似非负数的语句来满足静态分析器。

要解决第二个问题,有很多方法可以确定IEnumerable<>结构是否为非空。列出一些由System.Linq命名空间启用的内容:

  • elements.Any() //检查是否存在至少一个元素O(1)。
  • elements.Count() //计算所有元素,O(n)
  • elements.Single() //如果存在多个元素,则引发异常,O(1)。
  • elements.First() //返回第一个元素,如果为空,则引发异常,O(1)。

以下两个变体等同于elements.Any(),其中T是容器中元素的类型:

  • elements.SingleOrDefault() != default(T)
  • elements.FirstOrDefault() != default(T)

答案 1 :(得分:0)

elements.Count<long>()会为您计算IEnumerable<long>。你仍然想检查计数,因为一些方法会在空IEnumerable(例如Single&lt;&gt;)上抛出异常。

答案 2 :(得分:-1)

  

我的意思是,传递一个非空值   已经意味着它包含至少   零元素?

没有。相当一些API#s返回一个IEnumerable实际上会一直返回一些东西 - 只是空的。

  

我该怎么检查计数   (或建议的最大值)   IEnumerable的?

实际上这是真正的问题。 Enumerable没有API。