Контракты кода продолжают выдавать мне предупреждения «Возможно, вызов метода по нулевой ссылке» для всех моих операторов 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)]
Но и это не сработало. Итак, я решил, что просто добавлю явную нулевую проверку в предложение «where» оператора LINQ:
public IEnumerable<string> GetCarModelsByMake(string make)
{
return from car in Cars
where car != null && car.Make == make
select car.Model;
}
Это успешно избавляет от предупреждения о предложении «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;
}
Ясно, что это не очень чистый или эффективный код, и я на самом деле не собираюсь добавлять такие избыточные нулевые проверки ко всем моим операторам LINQ - особенно когда я знаю, что перечисление не содержит никаких нулевых записей. Лучшим решением этой проблемы было бы, чтобы средство статической проверки понимало операторы Contract.Assume, которые гарантируют ненулевые значения для каждого элемента в коллекции, но если это невозможно сделать, то, по крайней мере, соблюдайте атрибут SuppressMessage в методе .