如何避免代码重复

7
我有三个C#方法,它们的表现几乎相同。更具体地说,有大量重复代码,但最终它们执行不同的功能。
这显然非常低效,那么削减代码重复的最佳方法是什么?我应该将所有内容放在一个方法中,并在结尾使用 switch 和枚举来实现不同的功能吗?或者,是否有某种方式可以拥有3个单独的类并从另一个类继承共享部分?我已经阅读了很多相关信息,据我所知,这只用于从完全不同的类中获取属性。

1
(我用“重复使用”代替了“重复利用”,因为它似乎更清楚地表达了您的意思) - Marc Gravell
不要这样做!我应该把它们都放在一个方法中,然后在结尾处使用switch和enum来实现不同的功能吗? - SingleNegationElimination
你不会得到一个有用的答案,尝试发布一个包含这3个方法代码的问题,那么人们可能能够帮助你。重构代码没有一种通用的解决方案。 - Ian Ringrose
谢谢Marc。TokenMacGuy,你能详细解释一下为什么这是错误的吗?我之前在方法中使用int参数来设置“模式”,但我在一篇文章中被建议改用枚举。 - Jonathan
9个回答

5

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


谢谢Steven,结果正是我在寻找的。很抱歉我没有提供代码示例,下次我会注意的。 - Jonathan

4

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

当你分解每个功能时,你会开始看到重复的东西,这些应该被合并为一个函数。


1
在编程中提到单一职责原则是一个加分项:类和函数应该只做少量的事情,但是要做好它们。详情请参见:http://en.wikipedia.org/wiki/Single_responsibility_principle - Stephane Rolland

4
我有三个C#方法,它们大部分都执行相同的操作。虽然它们在最后执行不同的功能,但存在很多代码重复。
通过阅读这行文字,我认为您的三种方法根据不同的场景有不同的实现方式。
因此,我建议您看一下策略模式,可能会对您有用。 请点击这里

3

你想要的是好迹象。

这显然非常低效。

现在来说,低效(略微增加一点内存使用)是最不重要的部分。最关键的是它是一个维护噩梦。例如,如果你在例程中发现了一个错误并进行修复,那么你需要记得同时修复重复的代码。你肯定希望尽可能减少重复的代码。

或者,有没有某种方法可以拥有3个单独的类,并从另一个类继承共享部分?我已经阅读了很多相关资料,据我所知,这仅用于从完全不同的类中获取属性。

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

但是有很多种方法可以解决这个问题。没有更多的细节很难说出最好的方法。


2

没有一种解决方案能在所有情况下都适用,请展示给我们代码。

问题在于,当您把代码放入一个函数中并在某个地方切换一小部分行为时,会增加代码复杂性,有时保留一些重复的代码可能更好。

几乎相同的论点也适用于继承。您可以轻松地将通用代码塞入共同的祖先类中,但如果您开始将继承作为代码重用工具进行例行使用,则设计可能会滑入痛苦的世界。继承意味着代码在一段代码中可以影响其他代码中的行为,在您知道之前,您将拥有一个交织在一起的代码球,几乎不可能在不破坏的情况下进行更改。

通常最好的方法是从这三个函数中提取或抽象出一些有意义的公共代码部分。像高级模式这样有意义的东西,而不仅仅是一些共同的无关紧要的代码行。一个简单的规则可能会帮助您命名提取的代码:是否有明显、自然的方式来命名这个代码块?它是否明显适合您的某个类?如果是这样,它可能是一个好的解决方案。如果您很难命名它,并且它可以放在任何地方,您可能需要再思考一下。


2

您可以尝试通过将方法变为高阶或通用函数来概括该方法。其他方法包括设计模式,如模板方法,它允许您定义算法的框架,并让子类重新定义某些步骤。


2

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

    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建议的那样使用委托实例? - Jonathan
我认为,是的,你应该这样做。 - decyclone

1
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;
    }
}

0

没有人提到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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接