コード コントラクトは、すべての 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 属性を尊重します。 .