2014-10-26 2 views
0

я это следующим кодуПочему компилятор меняется, если условие тройного оператора

public static void Method() 
{ 
    AutoResetEvent autoReset = new AutoResetEvent(false); 
    bool canceled = false; 

    new Thread(() => 
    { 
     Thread.Sleep(1000); 
     canceled = true; 
     autoReset.Set(); 
    }).Start(); 

    do 
    { 
     Console.WriteLine("Doing something"); 
    } while (autoReset.WaitOne() && !canceled); 

    Console.WriteLine("Completed"); 
} 

И я пытаюсь achived покрытия коды 100%. Так что я только что сделал простой тест (что тест ничего, но это не точка), пробежал его и анализировал покрытие кода:

[TestMethod] 
public void TestMethod1() 
{ 
    Program.Method(); 
} 

Покрытие код дал мне, что была выполнена только часть while линии :

Code coverage

После некоторых исследований я попытался декомпилировать код и выяснил, что компилятор меняется мой do while к:

do 
{ 
    Console.WriteLine("Doing something"); 
    flag = (!autoResetEvent.WaitOne() ? false : !flag1); 
} 
while (flag); 

Так что false в условном операторе никогда не тестировался (и невозможно проверить because WaitOne never returns false. Простым решением является простое удаление WaitOne состояния while и внутри do. Так что я задаю следующие вопросы:

  1. Почему компилятор меняет условия на условный оператор?
  2. Есть ли способ предотвратить выполнение компилятором, сохраняя условие, подобное тому, которое находится во времени и не влияет на то, как скомпилировать остальную часть кода? В действительности условие в то время более сложное, чем это. Было бы проще и понятнее просто сохранить это так.
+1

Почему вы думаете, что это результат компилятора, а не декомпилятора? – Dmitry

+0

Хороший вопрос. Я предположил, что это был результат компилятора, потому что он был последовательным, почему я не был охвачен до 100%. Является ли публикация IL доказательством того, что это результат компилятора? –

+1

Покрытие кода - действительно опасная метрика. 100% -ый охват ничего не говорит о качестве вашего кода или тестовых случаях - вы все равно можете пропустить критические тестовые примеры и ошибки даже при 100% -ном охвате кода. Не стреляйте за 100% покрытие, просто чтобы получить его. –

ответ

2

&& оператор в C# является условным оператором, или более широко известной как оператор короткого замыкания. Оправа правой стороны оценивается только в том случае, если левая сторона оценивается как true. Это означает, что даже если вы не видите его в исходном коде, ветвь существует в скомпилированном коде, чтобы обойти оценку правой стороны в любое время, когда левая сторона равна false.

Это может повлиять на покрытие кода различными способами. Если вы измеряете branch coverage, то единственным способом достижения покрытия 100% будет создание теста, в котором autoResetEvent.WaitOne() возвращает false (например, mocking). Тем не менее, если вы измеряете охват по другим показателям (например, покрытие заявлений), вам может не понадобиться ничего делать для достижения 100% -ного охвата.

+0

Так что, если я правильно вас понимаю, выстрел-циркация существует только в C# и не существует в IL? –

+0

В CIL нет кода '&&' op, поэтому компилятор преобразует его в эквивалентное поведение с помощью инструкций ветвления. –

+0

Отлично! В этом есть смысл. Спасибо за ответ –

Смежные вопросы