C# 为什么可以';这个合同主张不能被证明吗?
我有一个类似这样的类:C# 为什么可以';这个合同主张不能被证明吗?,c#,.net,code-contracts,C#,.net,Code Contracts,我有一个类似这样的类: class Foo { private IEnumerable<Bar> bars; ... private void DoSomething() { Contract.Requires(bars != null); Contract.Requires(bars.Any()); Bar result = bars.FirstOrDefault(b => SomePred
class Foo
{
private IEnumerable<Bar> bars;
...
private void DoSomething()
{
Contract.Requires(bars != null);
Contract.Requires(bars.Any());
Bar result = bars.FirstOrDefault(b => SomePredicate) ?? bars.First();
Contract.Assert(result != null); // This asserts fails the static checker as "cannot be proven"
}
}
class-Foo
{
私人酒吧;
...
私人无效剂量()
{
合同要求(条数!=空);
合同。要求(bar.Any());
Bar result=bars.FirstOrDefault(b=>SomePredicate)??bars.First();
Contract.Assert(result!=null);//此断言使静态检查程序失败,因为“无法验证”
}
}
据我所知,合同拥有它需要知道的所有信息,result
将不会为空<代码>条中至少有一个元素。如果其中一个元素与SomePredicate
匹配,result
将是第一个这样的元素。如果不是,则结果
将是条中的第一个元素
为什么断言会失败?集合
栏
可能仍然包含空的项。如果该项是第一项,那么结果仍然可以是null
如果条的第一个元素是null
,该怎么办?(A:断言失败。)您没有确保或假设条中的元素不为空。尝试:
Contract.ForAll(bars, x => x != null);
或者(您的实际不变量):
或者Contract.Requires(bar.Any(x=>x!=null))
@leppie:这两种形式中有哪一种是首选的?我在用户文档中所能找到的只是“也可以使用扩展方法System.Linq.Enumerable.Any
而不是Contract.Exists
”@Matthew:如果永远不可能有空元素,那么就使用for All
,否则Any
就可以了。在使用Any
时,您还必须在代码的后半部分首先使用(x=>x!=null)
。细微的差别。
Contract.Requires(bars.FirstOrDefault(x => SomePredicate(x)) != null
|| bars.First() != null);