2

コード コントラクトは、すべての LINQ ステートメントに対して「null 参照でメソッドを呼び出している可能性があります」という警告を表示し続け、それらを黙らせる方法が見つかりません。たとえば、次のメソッドでは、最初に null をチェックせずに「car」オブジェクトの「Make」および「Model」プロパティにアクセスしているため、このような警告が 2 つ生成されます。

    public IEnumerable<string> GetCarModelsByMake(string make)
    {
        return from car in Cars
               where car.Make == make
               select car.Model;
    }

私の特定のケースでは、 Cars コレクションに null エントリが含まれることは決してないことがわかっているので、次のように Assume をメソッドに追加して、静的チェッカーを無音にすることができると考えました。

    public IEnumerable<string> GetCarModelsByMake(string make)
    {
        Contract.Assume(Cars.All(car => car != null));

        return from car in Cars
               where car.Make == make
               select car.Model;
    }

おそらく、静的チェッカーが理解することを期待するには少し多すぎるためです。そこで、次の SuppressMessage 属性を使用して警告を抑制することにしました。

    [SuppressMessage("Microsoft.Contracts", "NonNull")]

しかし、何らかの理由で、警告を抑制することができません。次の SuppressMessage 属性も試しましたが、どれも機能しませんでした。

    [SuppressMessage("Microsoft.Contracts", "Requires")]
    [SuppressMessage("Microsoft.Contracts", "Ensures")]
    [SuppressMessage("Microsoft.Contracts", "Invariant")]

ContractVerification 属性を使用して、メソッドのコントラクト検証を完全に無効にしようとさえしました。

    [ContractVerification(false)]

しかし、それもうまくいきませんでした。そこで、LINQ ステートメントの "where" 句に明示的な null チェックを追加することにしました。

    public IEnumerable<string> GetCarModelsByMake(string make)
    {
        return from car in Cars
               where car != null && car.Make == make
               select car.Model;
    }

これにより、「where」句の警告は正常に取り除かれますが、「select」句の警告は解消されません。実際、両方の警告を実際に取り除く唯一の方法は、次のように LINQ ステートメントのすべての句に null チェックを追加することです。

    public IEnumerable<string> GetCarModelsByMake(string make)
    {
        return from car in Cars
               where car != null && car.Make == make
               select car == null ? null : car.Model;
    }

明らかに、これはあまりきれいで効率的なコードではありません。実際には、すべての LINQ ステートメントにそのような冗長な null チェックを追加するつもりはありません。特に、列挙に null エントリが含まれていないことがわかっている場合はなおさらです。この問題の最善の解決策は、静的チェッカーが、コレクション内の各項目の非 null 値を保証する Contract.Assume ステートメントを理解することですが、それができない場合は、少なくともメソッドの SuppressMessage 属性を尊重します。 .

4

2 に答える 2

5

車のヌルチェックについて不平を言っている可能性があります。これを試して:

public IEnumerable GetCarModelsByMake(string make)
{
    if (null == 車)
        新しい文字列を返します[0]; // または必要に応じて null

    車で車から戻る
        どこで car.Make == make
        車を選択してください。
}

この LINQ ステートメントは、実質的に次のものと同じであることを思い出してください。

return Cars.Where(car => car.Make == make).Select(car => car.Model);

Cars が null の場合、例外が発生します。

于 2009-09-24T19:51:46.947 に答える
2

Code Contracts の最新バージョンを試しましたか? 10月にリリースされたものがありますが、これを再現することはできません.

ForAllあるいは、Code Contractsには静的クラスで定義された独自のメソッドがあり、LINQ 拡張メソッドContractsよりもそのロジックでうまく機能する可能性があります。All

于 2009-11-05T12:43:57.620 に答える