0

目前我有七个类似于以下代码的 if 语句:

if(hit.collider.gameObject.tag == "Colour1" && start_time > look_at_time)
{
    new_colour1.ChangeObjectMaterialColour(hit.collider.gameObject.renderer.material.color);

   var colums = GameObject.FindGameObjectsWithTag("column");
   foreach( GameObject c in colums)
    c.GetComponent<MeshRenderer>().materials[1].color = new_colour1.orignalMaterial;
}


else if(hit.collider.gameObject.tag == "Colour2" && start_time > look_at_time)
{
    new_colour2.ChangeObjectMaterialColour(hit.collider.gameObject.renderer.material.color);
    var colums = GameObject.FindGameObjectsWithTag("column");
    foreach( GameObject c in colums)
       c.GetComponent<MeshRenderer>().materials[1].color = new_colour2.orignalMaterial;
}

每个语句大约有 6 行代码,占用大量空间,阅读起来可能有点棘手。我想要做的是找到一种方法来重新考虑这一点,以便我的代码不那么笨重并且不占用太多空间。

我曾考虑将我的 if 语句集合更改为 switch 语句,但我发现 switch 语句不能像上面那样处理两个参数。如果有任何其他方式我可以重构我的代码但保持相同的功能,或者我是否坚持我的 if 语句集合?

编辑

更新为包含我的 7 个陈述中的两个。请注意,我正在尝试减少我拥有的 IF 语句的数量,或者找到一种更聪明的方法来执行它们。我不想添加更多额外的代码行或 if 语句。

4

2 回答 2

2

老实说,我认为在您的情况下,最具可读性和可维护性的只是将这些 if 块中的逻辑移动到函数中:

  if(hit.collider.gameObject.tag == "Colour1" && start_time > look_at_time)
    {
        DoTheThing(new_colour1);
    }
if(hit.collider.gameObject.tag == "Colour2" && start_time > look_at_time)
    {
        DoTheThing(new_colour2);
    }
//and so on



 void DoTheThing(MyType newColour)
  {
 newColour.ChangeObjectMaterialColour(hit.collider.gameObject.renderer.material.color);
      var colums = GameObject.FindGameObjectsWithTag("column");
       foreach( GameObject c in colums)
        c.GetComponent<MeshRenderer>().materials[1].color = newColour.orignalMaterial;
    }

至于使用switch你当然可以做这样的事情:

switch(hit.collider.gameObject.tag)
{
  case "Colour1":
      if (start_time>look_at_time)
      {
        //do something
      }
      else if (start_time<look_at_time)
      {
        //something else
      }
      else
      {
         //they are equal, etc, etc
      }
    break;
case "Colour2":
  //and so on
}

或者如果所有 if 块在 和 之间进行相同的比较start_timelook_at_time那么您可以将其反转:

enum TimeDifference
{
   LessThan,Equal,GreaterThan
}
//just one way to get a constant switchable value, not necessarily the best
var diff = TimeDifference.Equal;
if (start_time>look_at_time) {diff=TimeDifference.LessThan}
else if (start_time<look_at_time) {diff=TimeDifference.GreaterThan}

switch(diff)
{
  case TimeDifference.LessThan:
     switch(hit.collider.gameObject.tag)
     {
       case "Colour1":
         //do something for Colour1
        break;   
        case "Colour2":
         //do something for Colour2
        break;
      }//end switch Colour
     break;
  case TimeDifference.GreaterThan
    switch(hit.collider.gameObject.tag)
     {
       case "Colour1":
         //do something for Colour1
        break;   
        case "Colour2":
         //do something for Colour2
        break;
      }//end switch Colour
     break;  
   default:
    //nested switch for Colour in the == case, you get the idea.
}

尽管上述任何一个与几个格式良好且单独的if块的可读性是非常值得商榷的。

另一种方法是使用Dictionary<string,Action<int,int>>: (假设start_timelook_at_time都是ints 并且您的所有逻辑都以某种方式涉及它们)

var Actions = new Dictionary<string,Action<int,int>>();
Actions.Add("Colour1",(s,l)=>{
 if (start_time>look_at_time)
          {
            //do something
          }
          else if (start_time<look_at_time)
          {
            //something else
          }
          else
          {
             //they are equal, etc, etc
          }

});

然后你的主要代码变成 1 行:

Actions[hit.collider.gameObject.tag](start_time,look_at_time);

而且我确信还有更多方法可以重新排列该代码。

于 2013-10-25T08:36:17.837 回答
1

感谢您更新您的代码,现在我们可以开始查看重复的内容了。例如,这两个代码块之间的唯一区别是 if 语句中的字符串"Color1"和替换为"Color2"的变量。new_colour1new_colour2

从这里我建议如下:

//This should be declared once - e.g. class level not method level.
var colorDict = new Dictionary<string, [new_color_type]> 
                    {{"Colour1", new_colour1}, {"Colour2", new_colour2}};

[new_color_type] newColor;
if(start_time > look_at_time && colorDict.TryGetValue(
        hit.collider.gameObject.tag,
        out newColor))
{
   newColor.ChangeObjectMaterialColour(
                            hit.collider.gameObject.renderer.material.color);

   var colums = GameObject.FindGameObjectsWithTag("column");
   foreach( GameObject c in colums)
      c.GetComponent<MeshRenderer>().materials[1].color =
                                                    newColor.orignalMaterial;
}
于 2013-10-25T08:33:48.380 回答