Code Contracts продължават да ми дават предупреждения „Възможно извикване на метод при нулева препратка“ за всички мои LINQ изрази и не мога да намеря начин да ги заглуша. Например, следният метод генерира две такива предупреждения, защото имам достъп до свойствата „Make“ и „Model“ на обекта „car“, без първо да проверя за null.
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car.Make == make
select car.Model;
}
В моя конкретен случай знам, че колекцията 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;
}
Но това не работи, вероятно защото е твърде много да се очаква статичната проверка да разбере. Така че реших просто да потисна предупрежденията, като използвам следния атрибут SuppressMessage:
[SuppressMessage("Microsoft.Contracts", "NonNull")]
Но по някаква причина това не успява да потисне предупрежденията. Дори опитах и следните атрибути на SuppressMessage, нито един от които не работи:
[SuppressMessage("Microsoft.Contracts", "Requires")]
[SuppressMessage("Microsoft.Contracts", "Ensures")]
[SuppressMessage("Microsoft.Contracts", "Invariant")]
Дори се опитах напълно да деактивирам проверката на договора за метода, използвайки атрибута ContractVerification:
[ContractVerification(false)]
Но и това не проработи. Така че реших, че просто ще добавя изрична нулева проверка в клаузата "къде" на оператора LINQ:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car.Model;
}
Това успешно премахва предупреждението за клаузата "къде", но не елиминира предупреждението за клаузата "избор". Всъщност единственият начин, който открих да се отърва от двете предупреждения, е да добавя нулеви проверки към всяка клауза в оператора LINQ, така:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car == null ? null : car.Model;
}
Ясно е, че това не е много чист или ефективен код и всъщност не възнамерявам да добавя такива излишни нулеви проверки към всички мои LINQ изрази - особено когато знам, че изброяването не съдържа нулеви записи. Най-доброто решение на този проблем би било статичната проверка да разбере изразите Contract.Assume, които гарантират ненулеви стойности за всеки елемент в колекцията, но ако това не може да се направи, тогава поне спазвайте атрибута SuppressMessage на метода .