2012-04-30 24 views
32
int a, b, c; 

Constructor() 
{ 
    a = 5; 
    b = 10; 
    c = 15; 
    //do stuff 
} 
Constructor(int x, int y) 
{ 
    a = x; 
    b = y; 
    c = 15; 
    //do stuff 
} 
Constructor(int x, int y, int z) 
{ 
    a = x; 
    b = y; 
    c = z; 
    //do stuff 
} 

爲了防止「東西」和一些作業重複,我嘗試了類似:如何在保持可讀性的同時使用多個構造函數刪除重複的代碼?

int a, b, c; 

Constructor(): this(5, 10, 15) 
{ 
} 
Constructor(int x, int y): this(x, y, 15) 
{ 
} 
Constructor(int x, int y, int z) 
{ 
    a = x; 
    b = y; 
    c = z; 
    //do stuff 
} 

這適用於我想要做的,但我有時需要使用一些冗長的代碼來創建新對象或做一些計算:

int a, b, c; 

Constructor(): this(new Something(new AnotherThing(param1, param2, param3), 
    10, 15).CollectionOfStuff.Count, new SomethingElse("some string", "another 
    string").GetValue(), (int)Math.Floor(533/39.384)) 
{ 
} 
Constructor(int x, int y): this(x, y, (int)Math.Floor(533/39.384)) 
{ 
} 
Constructor(int x, int y, int z) 
{ 
    a = x; 
    b = y; 
    c = z; 
    //do stuff 
} 

此代碼與以前幾乎相同,只有正在傳遞的參數不可讀。我寧願做類似的事情:

int a, b, c; 

Constructor(): this(x, y, z) //compile error, variables do not exist in context 
{ 
    AnotherThing at = new AnotherThing(param1, param2, param3); 
    Something st = new Something(aThing, 10, 15) 
    SomethingElse ste = new SomethingElse("some string", "another string"); 

    int x = thing.CollectionOfStuff.Count; 
    int y = ste.GetValue(); 
    int z = (int)Math.Floor(533/39.384); 

    //In Java, I think you can call this(x, y, z) at this point. 
    this(x, y, z); //compile error, method name expected 
} 
Constructor(int x, int y): this(x, y, z) //compile error 
{ 
    int z = (int)Math.Floor(533/39.384); 
} 
Constructor(int x, int y, int z) 
{ 
    a = x; 
    b = y; 
    c = z; 
    //do stuff 
} 

基本上我在構造函數體內構建參數。然後我試圖將這些構建參數傳遞給另一個構造函數。我想我記得當用Java編碼時,能夠使用「this」和「super」關鍵字在另一個構造函數體內調用構造函數。在C#中似乎不可能。

有沒有一種方法可以輕鬆地做到這一點?我做錯了什麼嗎?如果這是不可能的,我應該堅持使用不可讀的代碼嗎?

我想我總是可以將重複的代碼切換到完全在構造函數之外的另一個方法。然後每個構造函數都會自己做,並調用其他構造函數共享的代碼。

回答

35

作爲替代呼叫從所有構造一個初始化方法(其防止您使用readonly字段)或工廠方法(其引入額外當你已經派生類的複雜性),則可以使用一個parameter object

int a, b, c; 

public Constructor() 
    : this(new ConstructorParameters()) 
{ 
} 

public Constructor(int x, int y) 
    : this(new ConstructorParameters(x, y)) 
{ 
} 

public Constructor(int x, int y, int z) 
{ 
    a = x; 
    b = y; 
    c = z; 
    //do stuff 
} 

private Constructor(ConstructorParameters parameters) 
    : this(parameters.X, parameters.Y, parameters.Z) 
{ 
} 

private class ConstructorParameters 
{ 
    public int X; 
    public int Y; 
    public int Z; 

    public ConstructorParameters() 
    { 
     AnotherThing at = new AnotherThing(param1, param2, param3); 
     Something st = new Something(at, 10, 15) 
     SomethingElse ste = new SomethingElse("some string", "another string"); 

     X = st.CollectionOfStuff.Count; 
     Y = ste.GetValue(); 
     Z = (int)Math.Floor(533/39.384); 
    } 

    public ConstructorParameters(int x, int y) 
    { 
     X = x; 
     Y = y; 
     Z = (int)Math.Floor(533/39.384); 
    } 
} 
+0

我想我可能實際上比工廠方法更喜歡這條路線。我很猶豫用工廠方法修改我的代碼,主要是因爲我使用了繼承。作爲新手程序員,我很難想象所有需要發生的變化。我在我的基類中有幾個重載的構造函數。派生類然後將它們自己的位添加到基礎構造函數中。根據派生類,需要不同的計算來查找某些參數。使用私有類來處理複雜的參數似乎是更簡單的方法。 – Cheese

+0

我決定採用另一種解決方案。閱讀您發佈的鏈接後,我開始閱讀同一站點上的「太多參數」頁面。通過閱讀,我認爲,也許構造函數由於傳遞給它們的所有參數而變得複雜。我決定從構造函數中刪除大部分參數。設置這些字段將在代碼的其他地方完成。我認爲我的實際問題是「我是否真的需要傳遞這麼多參數?」,而不是「我怎麼能用構造函數來做到這一點?」。由於您提供的鏈接引導我回答我的答案... – Cheese

+0

並且您發佈的答案是我認爲是我原始問題的最佳解決方案,我選擇您的答案作爲答案。 – Cheese

14

你可以做

Constructor() : this(5, 10, 15) 
{ 
} 
Constructor(int x, int y) : this(x, y, 15) 
{ 
} 
Constructor(int x, int y, int z) 
{ 
    int a = x; 
    int b = y; 
    int c = z; 
    //do stuff 
} 

但是如果你需要根據參數做一些花哨的邏輯,我會用一個factory pattern

public class myclass 
{ 
    private myclass(int x, int y, int z) 
    { 
    int a = x; 
    int b = y; 
    int c = z; 
    //do stuff 
    } 
    public static myclass Create() 
    { 
    AnotherThing at = new AnotherThing(param1, param2, param3); 
    Something st = new Something(aThing, 10, 15) 
    SomethingElse ste = new SomethingElse("some string", "another string"); 

    int x = thing.CollectionOfStuff.Count; 
    int y = ste.GetValue(); 
    int z = (int)Math.Floor(533/39.384); 

    return new myclass(x, y ,z); 
    } 
    public static myclass Create(int x, int y) 
    { 
    if (x = 1) 
     return new myclass(x, y, 2) 
    else 
     return new myclass(x, y, 15); 
    } 
    public static myclass Create(int x, int y, int z) 
    { 
    //so on and so forth 
    return new myclass(x, y, z); 
    } 
} 

雖然你不需要一個工廠模式,它絕對使您的構造函數邏輯可讀。

+0

我認爲這是我想要實現的體面解決方案。我的項目包含幾個將用於創建匿名對象集合的類。我認爲工廠模式可以應用於我的代碼中的多個位置。 – Cheese

+0

爲什麼C#中不可能在另一個構造函數中調用構造函數? (如果是的話) –

+0

@MakanTayebi肯定但有時你不想構造一個對象,如果參數是無效的。如果是這種情況,大多數情況下最好使用工廠模式,然後在構造函數中拋出異常。 –