C# “清除病理性嵌套”;if{}else{if{}else{if{…}}}};

C# “清除病理性嵌套”;if{}else{if{}else{if{…}}}};,c#,if-statement,nested,indentation,C#,If Statement,Nested,Indentation,我现在很不幸地在处理别人的C#代码,这真的让我大吃一惊。我不知道我之前的人是如何维护这段代码的,因为它的各种病态已经使IDE、编译器和运行时环境崩溃了 我今天面临的问题涉及一个15兆字节的源文件,它的特点是真正令人兴奋的病理嵌套。代码如下: if(var == 0) { // do stuff } else { if(var == 1) { // do stuff } else { if(var == 2) { // do stuff, identic

我现在很不幸地在处理别人的C#代码,这真的让我大吃一惊。我不知道我之前的人是如何维护这段代码的,因为它的各种病态已经使IDE、编译器和运行时环境崩溃了

我今天面临的问题涉及一个15兆字节的源文件,它的特点是真正令人兴奋的病理嵌套。代码如下:

if(var == 0) {
  // do stuff
}
else {
  if(var == 1) {
    // do stuff
  }
  else {
    if(var == 2) {
      // do stuff, identical word for word to the `var == 1` case
    }
    else {
      // etc.
    }
  }
}
在最好的情况下,这是一个值得商榷的文体选择。然而,这与代码的另一个病理学相结合:其中一些块有近千层的深度。(我费心测量的深度远远超过700。)我真诚地希望,在我之前的人,作为他们被迫脱离此代码之前的最后行动之一,运行一个样式工具,导致我之前的厌恶。我无法想象他们会像现在这样编写这段代码,特别是因为每三次或四次编辑代码就会导致IDE崩溃。(作为奖励,有时还会删除源文件的副本。)

我编写了一个简单的基于正则表达式的工具,试图压缩更简单的情况,但它似乎只处理了一半,然后破坏了这段特定的代码。(我不确定它是否会失败,因为这段代码还不时使用预处理器条件,或者因为最长的匹配长度接近10MB,Lua的正则表达式匹配器无法处理。)我希望有一种广泛使用的工具或技术可以扭转这个问题。我已经不得不使用astyle来清理代码中的其他一些风格“问题”。astyle的
--remove方括号
选项几乎满足了我的要求,但要求方括号内的语句是单行上的一条语句,这里的情况与此不同。。。(为了跨越我的“t”,我检查了一下;astyle并没有造成这个特殊的问题。)

编辑:对问题代码的深入检查揭示了以下内容:

#if OneThing
int num2296 = otherThing();
#endif
#if AnotherThing
int num44 = otherThing()
int num45 = 0;
#endif
int num72 = 0;
#if OneThing
int num45 = 0; // note: multiple equivalent declarations of num45
#endif
#if OneThing
for(int num2297 = 0; num2297 < num2296; ++num2297) {
  num45 = doSomething(num2297);
#endif
#if AnotherThing
for(int num43 = 0; num43 < num44; ++num43) {
  num45 = doSomething(num43);
#endif
  if(somethingElse(num45)) {
    ++num72;
  }
} // note: only one closing brace for the two protected by #ifs
#如果是一件事
int num296=其他事物();
#恩迪夫
#如果还有别的事
int num44=otherThing()
int num45=0;
#恩迪夫
int num72=0;
#如果一件事
int num45=0;//注:num45的多个等效声明
#恩迪夫
#如果一件事
for(int num297=0;num297
此代码的两个版本出于不同的目的进行编译,一个版本定义了一个东西,另一个版本定义了另一个东西。然而,这两个版本之间的大部分差异只是变量名,逻辑相同。(大多数,并非全部。)

像上面代码片段末尾的大括号这样的例子解释了我的简单工具为何会崩溃。这也越来越像是设计上的工作安全,而不像是无辜的无能。(如果代码曾经是由反编译器生成变量名(如
num2276
),那么现在就不是了。)


不幸的是,这意味着一个自动化的工具可能不会单独解决它。我只需要努力,慢慢地修复上一个程序员所造成的破坏。我把这个问题留在这里,希望有一个神奇的工具,我不知道,它可以将两个版本转换为SSA,识别并折叠它们的逻辑等价性,然后转换为将它们返回…

您可以使用Roslyn重写代码。将源代码修改为文本不是一种好方法。使用Roslyn,您可以将其修改为语法树

也许它能帮你把一切都弄平

if (a)
 if (b) F2()
 else F3();
else
 F4();
可能成为:

if (a && b) F2();
else if (a && !b) F3();
else F4();

这样,源代码就变成了一个简单的列表,在输入分支的条件下就更明显了。

切换案例可以是一个解决方案,或者对于示例中提供的代码来说,
switch
指令会好得多。顺便说一句:问题很好。我可能会通过将if块提取到方法来解决这个问题,而且会更深入r、 这段视频让我明白了我的意思(不是我的视频)。我链接到了一个相关的时间戳,但它很值得观看整个视频。它提供了重构一些非常可怕的代码的演练,但你的代码可能会超过它。当我看到这样的代码时,它有自动生成的味道。如果可能的话(可能不会)一些代码块/用例可以通过单元测试进行测试。如果是这样,一个好方法是为现有代码编写测试,然后对其进行反射。Roslyn看起来非常适合我希望做的事情。因为我对C不太熟悉,所以我会先尝试一些其他方法,但很高兴知道有这种工具可以依赖。(如果没有其他东西,当我得到我一直推迟的最后一个源文件时,它肯定会很有用…时钟超过25MB,其中至少15MB是制表符。O_O)也许那个家伙使用了Resharper功能“内联”将许多方法内联作为实施报复的一种方式。这样做时,代码大小可能会成倍增加。我看的代码越多,整个事情看起来就越恶意。我编辑了OP以演示另一层疯狂,这似乎会阻止使用Roslyn自动撤销损害。