2011-12-27 13 views
2

このタイプの質問に対する他の回答の一部を読んだ後、私はまだ警告が残っています。このスニペットで私は自分のデータベースからUserActivationを取得します。この時点までに、少なくとも1つのUserActivationが常に存在します。それ以上のものが1つあれば、すべての洋梨の形になっています...私は、証明されていないソースに関する警告をどのようにスケルチするのかについて、いくつかの指示に従っていますが、役に立たないものです。警告:警告83 CodeContracts:unproven:source!= null 161行目で、特定の行の下のメソッドを参照してください。コード契約:証明されていないソースが必要です!= null

これは、ここで要求されたとして、私は、CCのバージョン1.4.40602.0を使用しています方法

private static UserActivation GetUserActivation(Guid userId) 
    { 
     UserActivations userActivations = UserActivation.GetUserActivationsByUser(userId: userId); 

     Contract.Assume(userActivations != null); 

     if (userActivations.Count() > 1) // Line Number 161 
      throw new Exception("More then one user action found in database"); 

     return userActivations[0]; 
    } 

がUserActivations宣言です。

Public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid()) 
    { 
     Guid id = new Guid(); 
     if (user != null) 
      id = user.Id; 
     else 
      if (userId != Guid.Empty) 
       id = userId; 
      else 
       throw new Exception("Either user or userId must have a value"); 

     UserActivations uas = new UserActivations(StorageManager.SelectAll(
      Criteria.And(
      Criteria.EqualTo("UserId", id), 
      Criteria.EqualTo("Deleted", false)))); 

     Contract.Ensures(Contract.Result<UserActivations>() != null); 

     return uas; 
    } 
+0

リネオは本当ですか?私は 'userActivations [0];'が(別の)警告を飛ばしてしまうと思います。 'Count()'の署名はどういうものですか? Countプロパティはありませんか? –

+0

私はuserActivations [0]ではない行番号について確信しています。そうすれば、ideが信じるでしょう。 Count()シグネチャは単純にIEnumerable Count()です。public static int Count (このIEnumerable ソース)。 – Siegeon

+0

@HenkHolterman LINQ演算子、int System.Linq.Enumerable.Count (IEnumerable ソース) 'である必要があります。私はそれが 'require(source!= null)'を持っていると信じています。しかし、なぜそれが証明できないのか分かりません。仮定があります。 –

答えて

4

私はおそらくLINQ Enumerable拡張メソッドを避け、別の方法を使用してみます。ここ

public class UserActivations : BusinessListBase<UserActivation> 
{ 
    #region Constructors 
    internal UserActivations() 
    { 
    } 

    internal UserActivations(IList<UserActivation> list) 
     : base(list) 
    { 
    } 

    internal UserActivations(IEnumerable<UserActivation> list) 
     : base(list) 
    { 
    } 

とは、元のコードだったGetUserActivationByUser方法

public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid()) 
    { 
     Contract.Requires(user != null || userId != null, "Either user or userId must have a value"); 
     Contract.Ensures(Contract.Result<UserActivations>() != null); 

     Guid id = new Guid(); 
     if (user != null) 
      id = user.Id; 
     else 
      id = userId; 

     return new UserActivations(StorageManager.SelectAll(
      Criteria.And(
      Criteria.EqualTo("UserId", id), 
      Criteria.EqualTo("Deleted", false)))); 
    } 

です。 UserActivationsクラスには、インスタンスが保持する要素の数を決定するための独自のメソッドまたはプロパティがありませんか?いずれにしても

(シーケンスがICollectionを実装していない場合)、それは全体のシーケンスを列挙しますので、あなたは、シーケンスが空であるかどうかをテストするためにCount()拡張メソッドを使用しないでください。または、オブジェクトがIQueryableを実装する場合、Pavel Gatilovが指摘したように、Countは予期せずデータベースクエリを実行することがあります。

ここでは大きな要素はありませんが、要素が1つあると予想されますが、シーケンスには何千もの要素が定期的に含まれる場合があります。代わりに、Any()拡張メソッドを使用する必要があります。

Any()を使用すると、おそらく契約アナライザの観点から変わることはないため、UserActivationsクラスのCountプロパティを使用する必要があります(たとえばICollectionを実装すると仮定します)。

おそらく、あなたが契約アナライザをこのように助けることができる:あなたがUserActivationsクラスをコントロールしている場合、

private static UserActivation GetUserActivation(Guid userId) 
{ 
    UserActivations userActivations = UserActivation.GetUserActivationsByUser(userId: userId); 

    IEnumerable<UserActivation> e = (IEnumerable<UserActivation>)userActivations; 

    Contract.Assume(e != null); 

    if (e.Count() > 1) // Line Number 161 
     throw new Exception("More then one user action found in database"); 

    return userActivations[0]; 
} 

より良いソリューションを、メソッドがnullを返すことはありませんと言うことはGetUserActivationsByUserContract.Ensuresを追加することです。

+0

あなたは間違っています。 'Count()'は 'IEnumerable'インスタンスが実際に' ICollection'であればOKです。インスタンスは 'ICollection'を実装しているかどうかをチェックし、そうであればシーケンスを列挙するのではなく' Count'プロパティ値を返します。 –

+0

インスタンスが 'ICollection'を実装していない場合、' Count() 'を使うことは別の理由で悪いです:' IQueryable'の場合、 'Count()'はDBクエリを実行することがあります。 –

+2

@PavelGatilov型がICollectionを実装していることをプログラマが知っている場合は、ICollectionのcountプロパティを直接呼び出す方が良いでしょうか? 'Count()> 0'を使うことは、非コレクションの列挙型に対して' Count() 'が呼び出される悪い習慣です。 Countプロパティを持たないiteratorsのどこで使うのが最もよく見られます。 Where条件が計算上高価な場合、パフォーマンスはひどいです。 – phoog

2

ビルドログを確認してください。 Contract.Ensuresが正しく使用されていません。あなたは、このように、間違った使用のための警告を持っている必要があります。

警告CC1025を:CodeContracts:契約ブロックの後には、あなたの方法契約ブロックで定義されたローカル変数「のDataEvent」

の使用を見つけなければなりませんbe:

public static UserActivations GetUserActivationsByUser(User user = null, Guid userId = new Guid()) 
{ 
    Contract.Ensures(Contract.Result<UserActivations>() != null); 

    Guid id = new Guid(); 
    if (user != null) 
     id = user.Id; 
    else 
     if (userId != Guid.Empty) 
      id = userId; 
     else 
      throw new Exception("Either user or userId must have a value"); 

    UserActivations uas = new UserActivations(StorageManager.SelectAll(
     Criteria.And(
     Criteria.EqualTo("UserId", id), 
     Criteria.EqualTo("Deleted", false)))); 

    return uas; 
} 

私は証明できませんが、これが検証者を怒らせるかもしれないと思います。

実際、実行時のチェックをオンにすると、コードはコンパイルされず、ccrewriteは失敗します。

+0

投稿状況が一番上になるように私の方法はすでに更新されています。ありがとうございます。 – Siegeon

+0

@Siegeonええ、私は見ました。私は誰もが理由を見ることができるようにこれを引き出したいと思っていました。あなたの問題が解決したら、元のコードを元に戻して、他の人が元のコードを見ることができるようにしてください。 –

関連する問題