如何避免“source !=null”当使用代码契约和 Linq To Sql 时?

发布于 2024-09-05 10:49:14 字数 642 浏览 3 评论 0原文

我有以下使用正常数据上下文的代码,效果很好:

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:需要未经验证:源!= null

I have the following code using a normal data context which works great:

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

However when I convert the filter to an extension method like this:

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);
}

I get the following warning:

warning : CodeContracts: requires unproven: source != null

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

╭⌒浅淡时光〆 2024-09-12 10:49:14

我的猜测是,您的警告是由车主参数引起的,而不是由汽车引起的。在WithOwner方法中添加一个前提条件来检查owner是否不为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”进行了硬编码,因此没有问题,因为没有任何东西可以为空。

在第二个示例中,您创建了一个方法,静态编译器无法证明源(所有者)“永远不会为空”,因为其他代码可能会使用无效值来调用它。

My guess is that your warning is caused by the owner parameter, rather than the cars. Add a precondition in the WithOwner method to check if owner is not 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);
}

In your first code sample, you have 'Jim' hard-coded, so no problems there because there is not something which can be null.

In your second example you created a method for which the static compiler cannot prove that the source ( being owner ) 'will never be null', as other code might call it with an invalid values.

╄→承喏 2024-09-12 10:49:14

我想知道如何使用扩展方法编译代码,因为您在方法签名中缺少 this 关键字。

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

/KP

I wonder how you get the code compiled with the Extension method since you are missing this keyword in your method signature.

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

/KP

小矜持 2024-09-12 10:49:14

您的代码片段可能没有完全描述您正在使用的代码。

考虑这个片段:

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);
}

在这个片段中,运行时可能会抱怨您提到的警告,但它并不是抱怨 Cars 可能为空,而是抱怨 WithOwner< 的结果/code>(传递到Select)可能为空。

您可以通过确保扩展方法的结果不为 null 来满足运行时的要求:

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

此约定应该没问题,因为 Where 不会返回 null,而是返回一个 Enumerable.Empty;() 当没有匹配项时。

Its possible that your code snippet does not completely describe the code you are using.

Consider this snippet instead:

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);
}

In this snipped its likely the runtime will complain with the warning you mentioned, but it is not complaining about Cars possibly being null, it is complaining about the result from WithOwner (passed into Select) possibly being null.

You can satisfy the runtime by ensuring that the result from your extension method will not be null:

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

This contract should be ok because Where will not return null, but instead returns an Enumerable.Empty<T>() when there are no matches.

高冷爸爸 2024-09-12 10:49:14

我们在几个版本之前修复了这个问题。该警告是由于缺少有关 Linq 表达式构造等的一些约定。Linq 表达式方法具有约定,并且 C# 编译器生成调用这些方法的代码。如果我们在被调用的方法上没有足够的后置条件,那么您可能会收到这些关于您甚至不知道其存在的代码的神秘警告(除非您使用 ILdasm 查看)。

We fixed this a few releases back. The warning was due to some missing contracts around Linq expression construction etc. Linq expression methods have contracts and the C# compiler generates code that calls these methods. If we don't have enough post conditions on the called methods, then you can get these cryptic warnings about code that you don't even know is there (unless you look with ILdasm).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文