我使用正常数据上下文的代码如下:
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:需要unproven:source!= null
答案 0 :(得分:1)
我的猜测是你的警告是由所有者参数引起的,而不是汽车引起的。在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'硬编码,所以没有问题因为没有可以为null的东西。
在第二个示例中,您创建了一个方法,静态编译器无法证明源(所有者)'永远不会为空',因为其他代码可能会使用无效值来调用它。
答案 1 :(得分:0)
我想知道如何使用Extension方法编译代码,因为您在方法签名中缺少 this
关键字。
public static IQueryable<Car> WithOwner(this IQueryable<Car> cars, string owner)
{
...
}
/ KP
答案 2 :(得分: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);
}
在此剪切中,运行时可能会抱怨您提到的警告,但它并没有抱怨Cars
可能为空,它抱怨来自WithOwner
的结果(传递给{{ 1}})可能为null。
您可以通过确保扩展方法的结果不为null来满足运行时:
Select
此合约应该没问题,因为Contract.Ensures(Contract.Result<IQueryable<Car>>() != null);
不会返回null,而是在没有匹配时返回Where
。
答案 3 :(得分:0)
我们修复了几个版本。警告是由于Linq表达式构造等方面缺少一些合同.Linq表达方法有契约,C#编译器生成调用这些方法的代码。如果我们对被调用的方法没有足够的后置条件,那么你可以得到关于你甚至不知道的代码的这些神秘警告(除非你看看ILdasm)。