Is there a way to make Code Contracts work with LINQ?
Code contracts keep giving me "Possibly method call on null reference" warnings for all my LINQ statements, and I can't find a way to disable them. For example, the following method generates two such warnings because I access the Make and Model properties of the car object without first checking for a null value.
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car.Make == make
select car.Model;
}
In my particular case, I know that the Cars collection will never contain any null entries, so I figured I could just add an Accept method to the method to silence the static check, for example:
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;
}
But that doesn't work, presumably because it's too much to expect the static controller to understand. So, I decided to just suppress the warnings using the following SuppressMessage attribute:
[SuppressMessage("Microsoft.Contracts", "NonNull")]
But for some reason, this cannot suppress the warnings. I even tried the following SuppressMessage attributes, none of which worked:
[SuppressMessage("Microsoft.Contracts", "Requires")]
[SuppressMessage("Microsoft.Contracts", "Ensures")]
[SuppressMessage("Microsoft.Contracts", "Invariant")]
I even tried to completely disable contract validation for a method using the ContractVerification attribute:
[ContractVerification(false)]
But that didn't work either. So I figured I'd just add an explicit null check in the "where" clause of the LINQ statement:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car.Model;
}
This successfully removes the warning in the "where" clause, but it does not remove the warning for the "select" clause. In fact, the only way I've found to get rid of both warnings is to add null checks to every clause in the LINQ statement, like so:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car == null ? null : car.Model;
}
Obviously, this is not very clean or efficient code, and I'm not really going to add such redundant null checks to all my LINQ operators, especially when I know the enumeration does not contain any null entries. The best solution to this problem would be for the static validator to understand the Contract.Assume conventions that enforce nonzero values ββfor every item in the collection, but if that can't be done, then at least read the SuppressMessage attribute for the method.
source to share
He may be complaining about zero check of cars. Try the following:
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; }
Remember that this LINQ operator is actually the same as:
return Cars.Where (car => car.Make == make) .Select (car => car.Model);
You will get an exception if Cars is null.
source to share