Как правило, вы не можете статически анализировать поведение кода, поскольку оно может зависеть от среды, такой как файлы и пользовательский ввод.
Вы можете запустить программу и записать поведение как последовательность вызовов методов с параметрами и возвращаемыми значениями, используя мой Runtime Flow инструмент:
void Program.Main([])
void Program.WriteToConsole("Hello World!")
void Console.Write("Hello World!")
>SyncTextWriter Console.get_Out()
void SyncTextWriter.Write("Hello World!")
void StreamWriter.Write("Hello World!")
void StreamWriter.CheckAsyncTaskInProgress()
>void String.CopyTo(0, [�, �, �, �, �, �, �, �, �, ...246..., �], 0, 12)
void StreamWriter.Flush(true, false)
>12 EncoderNLS.GetBytes([H, e, l, l, o, , W, o, r, ...246..., �], 0, 12, [0, 0, 0, 0, 0, 0, 0, 0, 0, ...247..., 0], 0, false)
>void __ConsoleStream.Write([72, 101, 108, 108, 111, 32, 87, 111, 114, ...247..., 0], 0, 12)
>void __ConsoleStream.Flush()
Но если ваша программа генерирует графический вывод или вносит изменения в базу данных, вам нужны другие инструменты.
Кстати, использование автоматизированных инструментов для проведения рефакторинга, безусловно, сохраняет поведение программы.