2016-06-08 74 views
2

我正在C#中写一些代码,我注意到下面的情况。我想知道如何让这个更优雅和容易维护。方法重载或更优雅?

如果我有以下与重载

public void DoSmtg(string a) { DoSmtg(a, 0, 0f); } 
public void DoSmtg(string a, int x) { DoSmtg(a, x, 0f); } 
public void DoSmtg(string a, int x, double d) { // method logic } 

情景说,现在我需要添加另一个布尔参数。我将不得不修改这

这是一个非常简单的例子。可以说有10个以上版本的DoSmtg()方法。很明显,这段代码有味道。虽然超载是相当有效的,它显然使,因为它很难维持这样的代码:

  1. 有很多方法将被写入

  2. 并不明显,其方法被调用,直到缜密侦查(特别是如果方法有多个参数)

  3. 方法被越来越多通过参数列表

  4. 添加了新的参数需要在很多地方变化poluted(想想实现方法具ds以上从多个不同位置调用)

什么是一种优雅,简单和良好的方式来避免这样的事情?

+5

如果这些参数有任何相关性,请考虑将它们打包到一个类中,并使'.DoSmtg'成为该类的一个方法。 –

+1

@JeroenMostert说什么;我只是在输入相同的评论。 :)或者即使'DoSmtg'不是该类的成员,也许这些形式是相关的配置数据;那么专门为这个概念进行抽象并将其传递给'DoSmtg'可能是值得的。 (当然,这只是将问题推到了一个级别;现在,您对抽象的构造函数也有同样的问题。) –

+1

https://en.wikipedia.org/wiki/Builder_pattern – sstan

回答

3

你可以尝试在一个函数将所有的参数,使用默认值,当你调用命名参数功能:

public void DoSmtg(string a, int x=0, double d=0f, bool doIt=false) { 
    // method logic 
} 

当调用的函数,那么你会怎么做:

DoSmtg("yo!") 
DoSmtg("yo!", d:0.59, doIt:true) 
+0

请记住,这会破坏取决于其他重载的现有编译代码。 –

+1

好点。重新编译代码时也有可能中断。例如:在原始代码中,“Action a = DoSmtg;'是合法的;在新代码中它不是,这将成为一个错误。 –

+1

Visual Studio有很好的重构支持;) –

3

你可以包装所有的参数了在POCO:

public class SomethingParameters 
{ 
    public string A { get; set; } 
    public int X { get; set; } 
    public double D { get; set; } 
    public bool DoIt { get; set; } 
} 

然后,该方法签名变为:

public void DoSmtg(SomethingParameters parameters) { // method logic } 

我喜欢这种模式,因为它很容易在将来扩展。如果您需要添加五个参数或可选参数,则没有问题!

你可以把它想:

var parameters = new SomethingParameters() 
{ 
    A = "foobar", 
    X = 123, 
    D = 0.123, 
    DoIt = false 
} 

DoSmtg(parameters); 

如果你有大量的代码调用,你不想打破,你可以保留现有的过载的老方法签名但他们调用新一个:

public void DoSmtg(string a, int x, double d, bool doIt) 
    => DoSmtg(new SomethingParameters() 
       { 
        A = a, 
        X = x, 
        D = d, 
        DoIt = doIt 
       }); 
+0

我喜欢你的想法,但我不知道如何调用该方法。我必须在每次调用中实例化类的实例并将其参数设置正确?像DoSmtg(新的SomethingParameters(A,X,D,DoIt));。我喜欢这个,但它对公共参数有问题,而且它似乎仍然是同样的问题。虽然更优雅。 – pixel

+0

@ dbnex14您也可以更早实例化类。我不确定你的意思是“它在公共参数上有问题”吗? –

+1

@ dbnex14您可以实例化类的实例,如new SomethingParameters {A = valueA,D = valueD}。你不需要重载SomethingParameters .ctor –

2

我更喜欢使用单独的类参数的选项。但也许,正如你所说,你已经在多个地方调用了该方法,并且不想修改它。
在这种情况下,您可以添加一个可选的参数:

public void DoSmtg(string a, int x, double d, bool doIt = false) 

没有有其他地方改变,除非你选择,你可以提供参数。

如果你发现自己这样做,我仍然会使用类编写额外的重载,并开始使用它。如果参数太多,可选参数也会变得混乱。

+0

谢谢@ScottHannen,但我已经有可选的参数。但问题仍然存在。如果我要添加一个新参数,我需要做大量的修改。 – pixel

+0

如果您只添加一个可选参数,则仅对方法本身和传递给可选参数的调用方的更改进行更改。 –