我的代码看起来像这样:
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是不是认不出这种情况?
答案 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];
}