Jam*_*ger 2 .net c# linq code-contracts
代码契约一直给我"可能在空引用上调用一个方法"警告所有我的LINQ语句,我找不到一种方法来使它们静音.例如,以下方法生成两个这样的警告,因为我正在访问"car"对象的"Make"和"Model"属性,而不首先检查null.
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car.Make == make
select car.Model;
}
Run Code Online (Sandbox Code Playgroud)
在我的特定情况下,我知道Cars集合永远不会包含任何空条目,所以我想我可以在方法中添加一个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;
}
Run Code Online (Sandbox Code Playgroud)
但这不起作用,大概是因为期望静态检查器理解它有点太多了.所以,我决定使用以下SuppressMessage属性来禁止警告:
[SuppressMessage("Microsoft.Contracts", "NonNull")]
Run Code Online (Sandbox Code Playgroud)
但由于某种原因,这无法抑制警告.我甚至尝试了以下SuppressMessage属性,其中没有一个工作:
[SuppressMessage("Microsoft.Contracts", "Requires")]
[SuppressMessage("Microsoft.Contracts", "Ensures")]
[SuppressMessage("Microsoft.Contracts", "Invariant")]
Run Code Online (Sandbox Code Playgroud)
我甚至尝试使用ContractVerification属性完全禁用该方法的合同验证:
[ContractVerification(false)]
Run Code Online (Sandbox Code Playgroud)
但这也不起作用.所以,我决定在LINQ语句的"where"子句中添加一个显式的空检查:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car.Model;
}
Run Code Online (Sandbox Code Playgroud)
这成功地消除了"where"子句的警告,但它没有消除"select"子句的警告.事实上,我发现实际上摆脱两个警告的唯一方法是向LINQ语句中的每个子句添加空检查,如下所示:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car == null ? null : car.Model;
}
Run Code Online (Sandbox Code Playgroud)
显然,这不是非常干净或高效的代码,我实际上并不打算在我的所有LINQ语句中添加这样的冗余空值检查 - 特别是当我知道枚举不包含任何空条目时.解决此问题的最佳方法是让静态检查器了解Contract.Assume语句,以确保集合中每个项目的非空值,但如果无法完成,那么至少要尊重该方法的SuppressMessage属性.
它可能会抱怨无效检查汽车.试试这个:
public IEnumerable GetCarModelsByMake(string make)
{
if (null == Cars)
return new string[0]; // or null if you like
return from car in Cars
where car.Make == make
select car.Model;
}
请记住,此LINQ语句实际上与以下内容相同:
return Cars.Where(car => car.Make == make).Select(car => car.Model);
如果Cars为null,您将获得异常.