2011-07-28 10 views
3

私はこのようになりますクラスを持っている:この契約アサーションを証明できないのはなぜですか?

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" 
    } 
} 

私の知る限り、契約それはresultがnullでないことを知るために必要なすべての情報を持っています。 barsには少なくとも1つの要素があります。これらの要素のいずれかがSomePredicateに一致する場合は、resultが最初の要素になります。そうでない場合、resultbarsの最初の要素になります。

なぜアサーションが失敗するのですか?

答えて

2

barsの要素がnullでないことを保証または仮定していません。試してみてください:

Contract.ForAll(bars, x => x != null); 

か(実際不変):

Contract.Requires(bars.FirstOrDefault(x => SomePredicate(x)) != null 
       || bars.First() != null); 
+0

または 'Contract.Requires(bars.Any(X => X = NULL)!)' – leppie

+0

@leppie:それらのどちらかフォームが優先されますか?私がユーザのドキュメントで見つけることができるのは、 "Contract.Exists'の代わりに拡張メソッド' System.Linq.Enumerable.Any'を使うことも可能です。 " –

+2

@Matthew:ヌル要素が存在しない場合は、 'ForAll'を実行してください。そうでなければ' Any'が動作します。 'Any'を使うときは、コードの後半に' First(x => x!= null) 'をつけなければなりません。小さく微妙な違い。 – leppie

4

barsには、まだnullという項目が含まれている可能性があります。その項目が最初の項目である場合、resultはまだnullになります。

1

barsの最初の要素がnullの場合はどうなりますか? (A:アサーションが失敗します。)

関連する問題