【问题标题】:How to avoid code duplication [closed]如何避免代码重复[关闭]
【发布时间】:2011-05-19 15:26:22
【问题描述】:

我有三个几乎执行相同的 C# 方法。更具体地说,有大量的代码重复,但最终它们执行不同的功能。

这显然是非常低效的,那么减少代码重复的最佳方法是什么?我应该将它们全部放在一种方法中并在最后使用开关和枚举来实现不同的功能吗?或者,是否有某种方式可以让您拥有 3 个单独的类并从另一个类继承共享位?我已经对此进行了相当多的阅读,据我所知,这仅用于从完全不同的类中获取属性。

【问题讨论】:

  • (我替换为“reuse” => “duplication”,因为它似乎更符合您的意思)
  • “我应该将它们全部放在一个方法中,并在最后使用开关和枚举来实现不同的功能吗?”请不要这样做!
  • 你不会得到这个问题的有用答案,尝试发布一个包含 3 种方法的代码的问题,然后人们可能会帮助你。重构代码没有唯一的解决方案。
  • 谢谢你,马克。 TokenMacGuy,您能否提供更多详细信息,说明为什么这是错误的?我以前有一个 int 参数来设置方法中的“模式”,但在一篇文章中建议我改用枚举。

标签: c# code-reuse


【解决方案1】:

没有人提到 lambda 函数,.NET 3.5 开发人员必须了解它们:

public MyCustomObject SetYoung(MyCustomObject myObj) 
{ 
    GeneralMethod(myObj => myObj.IsOld = False);
    return myObj;
} 

public void GeneralMethod(Func<TSourceObjectType,TResultObjectType> func)
{
    MyCustomObject myObj = new MyCustomObject(); // MyCustomObject implements 'TSourceObjectType'
    TResultObjectType res = func(myObj);
}

【讨论】:

    【解决方案2】:
    public MyCustomObject MethodBase(MyCustomObject myObj) 
    { 
        myObj.Name="FixedName";
        myObj.Surname="FixedSurname";
        myObj.Type = Types.Human;
        return myObj;
    } 
    
    
    public MyCustomObject SetOld(MyCustomObject  myObj) 
    { 
        MethodBase(); 
        myObj.IsOld = True;
        return myObj;
    } 
    
    public MyCustomObject SetYoung(MyCustomObject myObj) 
    { 
        MethodBase(); 
        myObj.IsOld = False;
        return myObj;
    } 
    
    public MyCustomObject SetIsDead(MyCustomObject myObj) 
    { 
        MethodBase(); 
        myObj.IsDead = True;
        return myObj;
    } 
    public void MainMethod(enum OperationType)
    {
        MyCustomObject myObj = new MyCustomObject();
        switch(OperationType)
        {
            case OperationTypes.Old:
                myObj = SetOld(myObj);
                break;
            case OperationTypes.Young:
                myObj = SetYoung(myObj);
                break;
            case OperationTypes.Dead:
                myObj = SetDead(myObj);
                break;
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是一个好兆头,它困扰着你。

      这显然效率很低

      现在效率低下(一点额外的内存使用)是最不重要的部分。至关重要的是,它是维护的噩梦。例如,如果您在例程中发现错误并修复它,您也需要记住修复重复的代码。你肯定想尽可能地排除重复的代码。

      或者,是否有某种方法可以让您拥有 3 个单独的类并从另一个类继承共享位?我已经对此进行了相当多的阅读,据我所知,这仅用于从完全不同的类中获取属性。

      子类可以直接访问其超类的所有公共和受保护成员。例如,如果您有一个带有 Poop() 方法的 Animal 类,则 Dog 和 Cat 子类可以共享该便便代码。

      但是有很多方法可以剥这只猫的皮。没有更多细节很难说什么是最好的。

      【讨论】:

        【解决方案4】:

        您可以尝试通过将其设为高阶函数或泛型函数来泛化该方法。想到的其他方法是模板方法之类的设计模式,它允许您定义算法的骨架,并让子类重新定义某些步骤。

        【讨论】:

          【解决方案5】:

          没有适用于所有情况的解决方案,请向我们展示代码。

          问题在于,当您将代码放入一个函数并在内部某处切换一小部分行为时,会提高代码复杂性,有时保留一些重复代码比这样做更好。

          几乎相同的参数适用于继承。您可以轻松地将通用代码填充到一个共同的祖先类中,但如果您开始经常使用继承作为代码重用工具,您的设计可能会陷入痛苦的世界。继承意味着一段代码中的代码可以影响其他代码段中的行为,并且在您知道之前,您将拥有一个相互连接的代码球,如果不中断几乎不可能更改。

          通常最好从这三个函数中提取或抽象出一些有意义的代码公共部分。有意义的东西,比如高级模式,而不是一些没有连贯工作的常见行。一个可以帮助您的简单规则是命名提取的代码:是否有一种明显、自然的方式来命名块?它显然适合您的课程吗?如果是这样,它可能是一个很好的解决方案。如果你很难命名它并且它几乎可以去任何地方,你可能想多想一下。

          【讨论】:

            【解决方案6】:

            没有看到代码很难给出具体的例子,但听起来你想将委托实例传递给方法

            【讨论】:

            • 谢谢 Steven,原来这正是我想要的。很抱歉我没有提供代码示例,下次我一定会提供。
            【解决方案7】:

            我有三个 C# 方法,主要是 做相同的事情。有很多 代码重复,但最后,他们 两者都执行不同的功能。

            通过阅读这一行,我认为您的三种方法根据一些不同的场景具有不同的实现。

            所以我建议看一次可能有用的 Stratgey 模式。 See here

            【讨论】:

              【解决方案8】:

              你能做类似以下的事情吗:

                  public void MethodBase()
                  {
                      Console.WriteLine("1");
                      Console.WriteLine("2");
                      Console.WriteLine("3");
                      Console.WriteLine("4");
                      Console.WriteLine("5");
                  }
              
                  public void Method1()
                  {
                      MethodBase();
                      Console.WriteLine("Method 1");
                  }
              
                  public void Method2()
                  {
                      MethodBase();
                      Console.WriteLine("Method 2");
                  }
              
                  public void Method3()
                  {
                      MethodBase();
                      Console.WriteLine("Method 3");
                  }
              

              【讨论】:

              • 谢谢 decyclone。我忘了说 MethodBase() 设置了许多变量,所有这些变量都需要从 Method1、Method2 和 Method3 中访问。这是否意味着我需要按照 Steven 的建议使用委托实例?
              • 我想,是的,你应该这样做。
              【解决方案9】:

              在我看来,你应该坐下来拿一张纸和一支笔。画出你的方法执行的每一个功能。请记住,函数/方法应该做一件且只有一件的事情。

              在你分解每一个功能后,你会开始看到重复的东西,这些东西应该组合在一起成为一个功能。

              【讨论】:

              最近更新 更多