编程时,通常会有多种方法来获得完全相同的行为。
我知道很多工具允许逐行比较代码文件。我正在寻找的是一种工具,可以在比较行为时提供帮助或完成整个工作。
我很清楚,在大多数情况下,在执行过程中的某些时候,副作用,内存状态,堆栈跟踪和许多其他事情会有所不同。我真的在寻找一种不会考虑所有这些因素的顶级比较。就像文字比较工具一样,可以轻松忽略空行和注释。
以下是一个例子:
1:
static void main()
{
string i = "Hello World!";
Console.Write(i);
}
2:
static void main()
{
string helloWorldString = "Hello World!";
Console.Write(helloWorldString);
}
3:
static void main()
{
string myString = "Hello World!";
WriteToConsole(myString);
}
static void WriteToConsole(string text)
{
Console.Write(text);
}
简单Hello World程序的3个示例应该表现相同,至少从用户的角度来看,不包括极端系统配置边缘情况。我希望同样的机器在所有三种情况下完全相同。
当然,至少从我的观点来看,对于计算机而言,这似乎是一项非常困难的任务。我不希望这样的工具是完美的,特别是当项目有多个类,表单,全局变量等时。
但是在进行一些重构时,快速抬头就像“随着你的改变,即使你没有注意到,行为也发生了变化”或“改变之前和之后的行为保持不变”将会有很长的路要走当谈到节省时间。
Visual Studio,Resharper中是否有这样的工具,或者在其他地方可用?
作为额外的练习,因为我很好奇,如果C#不存在,是否存在其他语言?是否有正在进行的已知项目?
答案 0 :(得分:2)
这不可能。一个问题是@BJMyers在评论中已经提到的停机问题。但另一个障碍是,即使你的小片段实际上也没有做同样的事情。让我们看看由他们产生的IL。首先是#1:
IL_0000: nop
IL_0001: ldstr "Hello World!"
IL_0006: stloc.0 // i
IL_0007: ldloc.0 // i
IL_0008: call System.Console.Write
IL_000D: nop
IL_000E: ret
和#2:
IL_0000: nop
IL_0001: ldstr "Hello World!"
IL_0006: stloc.0 // helloWorldString
IL_0007: ldloc.0 // helloWorldString
IL_0008: call System.Console.Write
IL_000D: nop
IL_000E: ret
嗯,它们是相同的 - 这并不奇怪,因为唯一的区别是变量名称不再存在于编译代码中。但现在#3:
IL_0000: nop
IL_0001: ldstr "Hello World!"
IL_0006: stloc.0 // myString
IL_0007: ldloc.0 // myString
IL_0008: call UserQuery.WriteToConsole
IL_000D: nop
IL_000E: ret
WriteToConsole:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: call System.Console.Write
IL_0007: nop
IL_0008: ret
正如您所看到的,它有3个指令(此处不计算nop
)。因此,您的工具需要检查IL并确定哪个输入产生的结果。这将导致我们回到暂停问题。当然,静态分析仪可以识别某些模式,但是一般的解决方案是不可能的。
如果您的目标是确保重构没有破坏任何内容,那么您可以做的最好的就是单元测试,就像@dktaylor在答案中已经建议的那样。
答案 1 :(得分:2)
通常,您无法静态分析代码行为,因为它可能取决于文件和用户输入等环境。
您可以使用我的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()
但是如果您的程序生成图形输出或进行数据库更改,则需要其他工具。
BTW,使用自动化工具执行重构肯定会保留程序行为。答案 2 :(得分:0)
我相信你所寻找的是单元测试。它们允许您测试某些功能的结果,而无需担心实现。看看这里: