2

コードコントラクトとlinqに問題があります。問題を次のコードサンプルに絞り込むことができました。そして今、私は立ち往生しています。

public void SomeMethod()
{
    var list = new List<Question>();

    if (list.Take(5) == null) { }
    // resharper hints that condition can never be true

    if (list.ForPerson(12) == null) { }
    // resharper does not hint that condition can never be true
}

public static IQueryable<Question> ForPerson(this IQueryable<Question> source, int personId)
{
    if(source == null) throw new ArgumentNullException();

    return from q in source
           where q.PersonId == personId
           select q;
}

私のlinqチェーンの何が問題になっていますか?ForPersonの呼び出しを分析するときに、なぜ「不平を言う」のではないのですか?

編集:ForPersonメソッドの戻りタイプが文字列からIQueryableに変更されました。(私の悪い)

4

2 に答える 2

4

Reshaperは、aTakeまたはの結果Skipがnullになることはないということは正しいです。アイテムがない場合、結果はIEnumerable<Question>要素を持たないanになります。私はあなたがチェックすべきことをしたいと思いますAny

var query = list.Take(5);
if (!query.Any())
{
    // Code here executes only if there were no items in the list.
}

しかし、この警告はどのように機能しますか?Resharperは、メソッド定義を見ただけでは、メソッドがnullを返さないことを知ることができません。また、メソッド本体をリバースエンジニアリングして、nullを返さないことを判断することはないと思います。したがって、.NETメソッドのSkipおよびTakeがnullを返さないことを指定するルールで特別にハードコーディングされていると思います。

独自のカスタムメソッドを作成する場合、Reflectorはインターフェイスからメソッドの動作について推測できますが、インターフェイスではnullを返すことができます。したがって、警告は発行されません。メソッド本体を分析した場合、nullは不可能であり、警告を発行できることがわかります。しかし、コードを分析してその可能な動作を判断することは非常に困難な作業であり、Red Gateが、はるかに低い開発コストでより有用な機能を他の場所に追加できるときに、この問題の解決にお金を費やすことをいとわないのではないかと思います。

ブール式がtrueを返すことができるかどうかを判断することは、ブール充足可能性問題と呼ばれ、NP困難な問題です。

Resharperで、一般的なメソッド本体がnullを返すことができるかどうかを判断する必要があります。これは、上記のNP困難問題の一般化です。100%の場合、どのツールでもこれを正しく実行できる可能性はほとんどありません。

于 2010-06-19T10:10:33.593 に答える
0
if(source == null) throw new ArgumentNullException(); 

それはコード コントラクトの方法ではありません。代わりに次のことを意味しますか。

Contract.Require(source != null);
于 2010-06-19T15:51:24.523 に答える