在 C# 代码中重构大型 if else 语句

Refactoring big if else stament in C# code

我有四个非常长的 if-else 代码。我该如何重构这段代码?

if (objectcameraangle > 140)
{
  if (Vector3.Distance(joint1, joint2) > 0.5)
  {
    Rfootikcontroller.transform.Translate((scx / 10000), scy / 10000, 0);
  }
  else
  {
    Rfootikcontroller.transform.Translate((scx / 800), scy / 800, 0);
  }
}
else if (objectcameraangle < 35)
{
  if (Vector3.Distance(joint1, joint2) > 0.5)
  {
    Rfootikcontroller.transform.Translate((-scx / 10000), scy / 10000, 0);
  }
  else
  {
    Rfootikcontroller.transform.Translate((-scx / 800), scy / 800, 0);
  }
}
else if (objectcameraangle > 35 && objectcameraangle < 140 && signed > 0)
{
  if (Vector3.Distance(joint1, joint2) > 0.5)
  {
    Rfootikcontroller.transform.Translate(0, scy / 10000, (-scx / 10000));
  }
  else
  {
    Rfootikcontroller.transform.Translate(0, scy / 800, (-scx / 800));
  }
}

如何将它重写为更好的东西。想在这里学习一些新东西。感谢您的帮助。

是这样的吗?

var distance = Vector3.Distance(joint1, joint2);
var divisor = distance > 0.5 ? 10000 : 800;

var scx2 = scx / divisor;
var scy2 = scy / divisor;

if (objectcameraangle < 35)
{
    Rfootikcontroller.transform.Translate(-scx2, scy2, 0);
}
else if (objectcameraangle < 140)
{
    if (signed > 0)
        Rfootikcontroller.transform.Translate(0, scy2, -scx2);
}
else
{
    Rfootikcontroller.transform.Translate(scx2, scy2, 0);
}

如果您使用的是最新版本的 C#(我认为是 8.0+?),您可以尝试如下操作:

var denominator = (Vector3.Distance(joint1, joint2) > 0.5 ? 10000 : 800);

switch (true) {
    case var _ when objectcameraangle > 140:
        Rfootikcontroller.transform.Translate((scx / denominator), scy / denominator, 0);
        break;
    case var _ when objectcameraangle < 35:
        Rfootikcontroller.transform.Translate((-scx / denominator), scy / denominator, 0);
        break;
    case var _ when objectcameraangle > 35 && objectcameraangle < 140 && signed > 0:
        Rfootikcontroller.transform.Translate(0, scy / denominator, (-scx / denominator));
        break;
}

希望能编译...显然,我没有你所有的可用对象,所以我无法检查自己。

查看您的代码,我发现了两点:

  • 几乎所有的代码都是为了所有的意图和目的,只需分配 4 个不同的变量,并且

  • 有fall-through/no-op个条件:当scx正好是35140,或signed是non-positive.

我会隔离每个变量的赋值并在最后调用 Translate() 方法,因此:

int angle = objectcameraangle // because, too many letters (and runtogetherwords)

int d = Vector3Distance > 0.5
      ? 10000
      :   800
      ;
int? x = angle > 140                              ?   scx / d
       : angle <  35                              ? - scx / d
       : angle >  35 && angle < 140 && signed > 0 ? 0
       : null // TODO what happens when objectcameraangle is exactly 35 or 140, or is signed <= 0?
       ;
int? y = angle > 140                              ?   scy / d
       : angle <  35                              ?   scy / d
       : angle >  35 && angle < 140 && signed > 0 ?   scy / d
       : null // TODO what happens when objectcameraangle is exactly 35 or 140, or is signed <= 0?
       ;
int? z = angle > 140 ? 0
       : angle <  35 ? 0
       : angle >  35 && angle < 140 && signed > 0 ? - scx / d
       : null // TODO what happens when objectcameraangle is exactly 35 or 140, or is signed <= 0?
       ;

// Wrapped in a guard clause to protect against the fall-through condition(s) noted above
if ( x != null && y != null && z != null ) {
  Rfootikcontroller.transform.Translate( x, y, z );
}

然后您可以将 4 个变量赋值中的每一个的逻辑提取到单独的方法中,使它们变得简单且易于测试。那会给你这样的东西:

static int SelectDistance( double v3Distance )
{
  return Vector3Distance > 0.5
       ? 10000
       :   800
       ;
}

static int SelectValue( angle int , signed int, v1 int, v2 int , v3 int , v4 int)
{
  return angle > 140                             ? v1
       : angle <  35                             ? v2
       : angle >  35 && angle < 140 && signe > 0 ? v3
       :                                           v4
       ;
}
.
.
.
int  angle = objectcameraangle // because, too many letters (and runtogetherwords)

int  d = SelectDistance( Vector3Distance );
int? x = SelectValue( angle, signed, scx/d, -scx/d,      0, null );
int? y = SelectValue( angle, signed, scy/d,  scy/d,  scy/d, null );
int? z = SelectValue( angle, signed,     0,      0, -scx/d, null );

// Wrapped in a guard clause to protect against the fall-through condition(s) noted above
if ( x != null && y != null && z != null ) {
  Rfootikcontroller.transform.Translate( x, y, z );
}