2016-06-08 57 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

如果您只添加一個可選參數,則僅對方法本身和傳遞給可選參數的調用方的更改進行更改。 –