6

私は通常のデータコンテキストを使用して次のコードを持っていますが、これはうまく機能します:

var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var cars = (from c in dc.Cars
            where c.Owner == 'Jim'
            select c).ToList();

ただし、フィルターを次のような拡張メソッドに変換すると、次のようになります。

var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var cars = dc.Cars.WithOwner('Jim');

public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
    Contract.Requires(cars != null);
    return cars.Where(c => c.Owner == owner);
}

次の警告が表示されます。

警告:CodeContracts:証明されていないものが必要です:source!= null

4

4 に答える 4

1

私の推測では、あなたの警告は車ではなく所有者のパラメータによって引き起こされていると思います。WithOwnerメソッドに前提条件を追加して、所有者がnullでないかどうかを確認します。

public static IQueryable<Car> WithOwner(IQueryable<Car> cars, string owner)
{
    Contract.Requires(cars != null);
    Contract.Requires(!string.isNullOrEmpty(owner));
    return cars.Where(c => c.Owner = owner);
}

最初のコードサンプルでは、​​「Jim」がハードコーディングされているため、nullになる可能性のあるものがないため、問題はありません。

2番目の例では、静的コンパイラがソース(所有者)がnullになることは決してないことを証明できないメソッドを作成しました。これは、他のコードが無効な値で呼び出す可能性があるためです。

于 2010-06-18T11:35:16.610 に答える
0

thisメソッドのシグネチャにキーワードがないため、拡張メソッドでコンパイルされたコードをどのように取得するのだろうか。

public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
    ...
}

/KP

于 2010-08-15T16:21:28.370 に答える
0

コード スニペットが、使用しているコードを完全に説明していない可能性があります。

代わりに、次のスニペットを検討してください。

var dc = new myDataContext();
Contract.Assume(dc.Cars!= null);
var models = dc.Cars.WithOwner('Jim').Select(c => c.Model);

public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
    Contract.Requires(cars != null);
    return cars.Where(c => c.Owner == owner);
}

この抜粋では、ランタイムがあなたが言及した警告で不平を言う可能性がありますが、null である可能性について不平を言っているのではなく、 (渡された)Carsからの結果が null である可能性について不平を言っています。 WithOwnerSelect

拡張メソッドからの結果が null にならないようにすることで、ランタイムを満たすことができます。

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

null を返さないため、このコントラクトは問題ありませんが、一致がない場合はWhere代わりに を返します。Enumerable.Empty<T>()

于 2011-09-12T21:08:29.130 に答える