#c# #visual-studio-2010 #code-coverage
#c# #visual-studio-2010 #покрытие кода
Вопрос:
class Program
{
static void Main(string[] args)
{
var x = new Program();
Console.Write(x.Text);
Console.Write(x.Num);
//Console.Write(x.Num);//line A
}
private string Text_;
public string Text
{
get
{
return Text_ ?? (Text_ = "hello");//line B
}
}
private int? Num_;
public int Num
{
get
{
return (int)(Num_ ?? (Num_ = 42));//line C
}
}
}
Я использую Visual Studio 2010 для получения результатов покрытия кода. Это показывает, что строка B полностью закрыта, а строка C частично закрыта. Я бы ожидал, что строка B также частично закрыта, а не полностью закрыта. Почему так получается, что результаты покрытия кода показывают, что строка B полностью покрыта?
Чтобы продемонстрировать, что оно работает «правильно» для свойства Num, раскомментируйте строку A и запустите покрытие. Оно должно показывать, что строка C полностью закрыта.
Когда я переписываю код в более подробную форму (см. Ниже), он работает правильно и сообщает, что Text_ частично закрыт. Я предпочитаю использовать первое из-за его краткости и хотел бы знать, эквивалентны ли эти две формы. Заранее спасибо.
if (Text_ != null)
{
return Text_;
}
else
{
return Text_ = "hello";
}
Ответ №1:
??
On Nullable<T>
расширяется до чего-то более сложного в компиляторе, т. Е.
a ?? b
это действительно
a.HasValue ? a.GetValueOrDefault() : b
Теперь, поскольку a
было null / empty в единственный раз, когда оно было выполнено, a.GetValueOrDefault()
оно никогда не вызывалось. Базовый код при использовании строки (или любой плоской ссылки) проще.
На самом деле, просто вызовите его дважды, чтобы это исчезло:
Console.Write(x.Text); // first call; performs init
Console.Write(x.Text); // test once initialized
Console.Write(x.Num); // first call; performs init
Console.Write(x.Num); // test once initialized
Комментарии:
1. Понял. Я должен был углубиться в синтаксический сахар, который я использовал, и моя предпосылка в любом случае неверна.
Ответ №2:
Не вдаваясь в IL, сгенерированный этой строкой, я бы заподозрил, что компилятор выполнил некоторую внутреннюю оптимизацию, из-за которой ваша «строка B» рассматривается как единый оператор.
Принципиальное различие между двумя операторами заключается в том, что строка B ссылается на объект, тогда как строка C использует сокращенную ссылку на Num_.Value
.
В общем, определенно не стоит беспокоиться о «100% покрытии кода» — как показывает этот пример, иногда инструментарий в любом случае неверен. Важно то, что большая часть кода покрыта, по крайней мере, основные пути выполнения через бизнес-логику.
Покрытие не заменяет проверки кода другим человеком.
Комментарии:
1. Действительно, не стоит беспокоиться о 100% покрытии, чего хочет мой босс, поэтому я намерен оправдать себя за части, которые я не могу покрыть. Если это не принято, я бы тоже не согласился работать здесь намного дольше.