为什么CodeContracts警告我“需要未经证实:index< @ this.Count”即使我已经检查了计数?

时间:2011-07-28 18:25:02

标签: c# .net code-contracts

我的代码看起来像这样:

public class Foo<T> : ObservableCollection<T>
{
    private T bar;

    public Foo(IEnumerable<T> items)
        : base(items.ToList())
    {
        Contract.Requires(items != null);

        if (this.Any())
            this.bar = this[0]; // gives 'requires unproven: index < @this.Count'
    }
}

Any不应该检查索引0的帐户吗?我做错了什么,或者CodeContracts是不是认不出这种情况?

2 个答案:

答案 0 :(得分:6)

LINQ的.Any和项目访问者[0]无关,因此尚未对代码合同进行考虑,认为它们是相同的。由于this.bar无论如何都会使用默认值进行初始化,因此最好这样做:

Contract.Requires(items != null);
this.bar = items.FirstOrDefault();

这不仅可以解决AakashM指出的线程安全的可能性,而且性能也略高一些。由于您知道this是一个集合(因此具有.Count),因此另一个选项是:

if(this.Count > 0)
    this.bar = this[0]; 

答案 1 :(得分:6)

没有一个LINQ方法使用Contracts API进行注释。因此,当验证程序在此方法上运行时,它不会获取有关Count值的新数据。这就是你看警告的原因。

解决此问题的一种方法是使用Assume告诉验证者此时计数是有效的。

if (this.Any()) {
  Contract.Assume(this.Count > 0);
  this.bar = this[0];
}