如果{} else {if {} else {if {…}}}“c# – 清理病态嵌套”

前端之家收集整理的这篇文章主要介绍了如果{} else {if {} else {if {…}}}“c# – 清理病态嵌套”前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我目前有不幸在Somebody Else的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来清理代码中的其他一些风格的“问题”. astire的–remove-bracket选项几乎完成了我想要的,但是要求括号内的语句是单行上的单个语句,这在这里非常不一样(只是为了跨越“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

代码的两个版本被编译为不同的目的,一个定义了OneThing,另一个定义了AnotherThing.然而,两者之间的大部分差异只是变量名,逻辑相同. (大多数,不是全部)

上面的代码段末尾的大括号就像为什么我的简单工具打破了.这也越来越像设计的工作安全,而不像无辜的无能. (如果代码曾经是由一个反编译器生成变量名称,如num2276的那一点,那么目前还不是这样).

不幸的是,这意味着一个自动化工具可能不会单独削减.我只需要通过,缓缓地解除最后程序员的伤害.我在这里离开这个问题,有一个奇迹工具,我不知道,可以将这两个版本转换为SSA,识别和折叠他们的逻辑等价,然后转换回来…

解决方法

您可以使用Roslyn重写代码.将源代码修改为文本不是一个好办法.使用Roslyn可以将其修改为语法树.

也许这有助于你平息一切?

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

可能变成:

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

这样,源代码就变成一个平面的列表,在什么条件下输入一个分支是更明显的.

猜你在找的C#相关文章