2012-07-27 81 views
1

給定下面的兩個類,我想用int參數調用Child構造函數,然後用int參數調用父構造函數,最後使用Child無參數構造函數。C#構造器鏈接

這可以在不使用可選參數的情況下完成嗎?

public class Parent 
{ 
    public Parent() 
    { 
     Console.WriteLine("Parent ctor()"); 
    } 

    public Parent(int i) 
    { 
     Console.WriteLine("Parent ctor(int)"); 
    } 
} 

public class Child:Parent 
{ 
    public Child() 
    { 
     Console.WriteLine("Child ctor()"); 
    } 

    public Child(int i) 
    { 
     Console.WriteLine("Child ctor(int)"); 
    } 
} 

這是我們希望完成在.NET 4邏輯.NET 2.0

public class Parent2 
{ 
    public Parent2(int? i = null) 
    { 
     Console.WriteLine("Parent2 ctor()"); 

     if (i != null) 
     { 
      Console.WriteLine("Parent2 ctor(int)"); 

     } 
    } 
} 

public class Child2 : Parent2 
{ 
    public Child2(int? i = null) 
     : base(i) 
    { 
     Console.WriteLine("Child2 ctor()"); 

     if (i != null) 
     { 
      Console.WriteLine("Child2 ctor(int)"); 
     } 
    } 
} 

這裏是生產代碼我們討論

public class DataPoint<T> 
{ 
    public DataPoint() { } 

    public DataPoint(T xValue, int yValue) 
    { 
     XAxis = xValue; 
     YAxis = yValue; 
    } 

    public T XAxis { get; set; } 
    public int YAxis { get; set; } 
} 

public class DataPointCollection<T> : DataPoint<T> 
{ 
    DataPointCollection() 
    { 
     Labels = new List<string>(); 
    } 

    DataPointCollection(T xValue, int yValue) 
     : base(xValue, yValue) 
    { } 

    public List<string> Labels { get; set; } 
} 

編輯:

此時此問題的原因是「Code Go如果「學習練習要以最少的代碼遵循DRY方法。正常模式是在類中使用一個內部私有函數,該函數具有從每個構造函數執行的通用代碼。

編輯2

我加的例子生產代碼。

+2

你只能一次鏈,並且可以」從父母到孩子的連鎖。 – Oded 2012-07-27 18:14:28

+1

你想在類的構造過程中調用同一個類的多個構造函數嗎?我認爲你甚至不會**那樣做。如果你解釋爲什麼你想這樣做,我相信我們可以幫助你想出一個不同的解決方案。 – 2012-07-27 18:14:37

+0

@Oded你錯了,**可以**多於一個鏈接調用(例如'Child():this(1)'和'Child(int val):base(val)'將有效地導致跟隨來電訂購:'父(INT),兒童(INT),兒童()' – 2012-07-27 18:17:21

回答

2

不,您不能這樣做,因爲您不能從Parent調用Child構造函數。

0

Inheritance只能作爲一種方式。

Child --->Parent

你可能有一個結構錯誤,因爲(有人糾正我,如果我錯了)不存在情況下,您會必須調用同一類的兩個構造馴服時間。

除遞歸構造函數外,因爲它調用它自己,所以它不是一回事。

0

您可以通過定義像這樣的Child(int i)構造完成你的問題的第一部分:

public Child(int i) : base(i) 
{ 
    Console.WriteLine("Child ctor(int)"); 
} 

但是,如前所述,以後就無法再調用另一個Child的構造函數。如果你的目標(假設這不是一個純粹的學術問題)確保總是執行Child的默認構造函數中包含的某些標準行爲,那麼將它封裝在一個方法中,然後從Child的構造函數:

public class Child:Parent 
{ 
    public Child() 
    { 
     Console.WriteLine("Child ctor()"); 
     CommonChildConstructionBehaviour(); 
    } 

    public Child(int i) : base(i) 
    { 
     Console.WriteLine("Child ctor(int)"); 
     CommonChildConstructionBehaviour(); 
    } 

    private void CommonChildConstructionBehaviour() 
    { 
     Console.WriteLine("All child constructors must call me."); 
    } 
} 
+0

這是我們用來保持DRY的正常模式。 – Sam 2012-07-27 18:27:46

1

如果您需要進行一系列的初始化方法,我建議你定義它們的方式 - 爲正常(不構造)的方法。你可以使用一個重寫的保護方法設置後的往復,因爲構造函數可以選擇任意組合或順序調用其初始化方法:

public class Parent { 

    public Parent() { } 

    public Parent(int i) { 
     initWithArg(i); 
     initNoArgs(); 
    } 

    virtual protected void initWithArg(int i) { 
     Console.WriteLine("Parent initWithArg(int)"); 
    } 

    virtual protected void initNoArgs() { 
     Console.WriteLine("Parent initNoArgs"); 
    } 
} 

public class Child : Parent { 

    // Override the *parameterless* constructor 
    public Child(int i) : base() { 
     initWithArg(i); 
     base.initWithArg(i); 
     initNoArgs(); 
    } 

    override protected void initWithArg(int i) { 
     Console.WriteLine("Child initWithArg(int)"); 
    } 

    override protected void initNoArgs() { 
     Console.WriteLine("Child initNoArgs"); 
    } 
} 
+0

是的,這和我下面的第二個可能的答案是一樣的。 – 2012-07-27 20:00:06

0

有幾個選擇,但他們都不是完善。最後,我的主要建議是,如果可以(顯然)升級到.NET 4.0。

這裏有一個選項,使用對象再投,因爲你需要的裏面有什麼。這是明顯的缺點,因爲你會失去打字或打破簽名,但它可能對你的情況下工作,我不知道:

public class Parent3 
{ 
    public Parent3(object i) 
    { 
     Console.WriteLine("Parent3 ctor()"); 

     if (i != null) 
     { 
      Console.WriteLine("Parent3 ctor(int)"); 
     } 
    } 
} 

public class Child3 : Parent3 
{ 
    public Child3(object i) 
     : base(i) 
    { 
     Console.WriteLine("Child3 ctor()"); 

     if (i != null) 
     { 
      Console.WriteLine("Child3 ctor(int)"); 
     } 
    } 
} 

這裏的另一種選擇,可使用init方法。但是,他們不會以完全相同的順序開火,但它可能適用於您。

public class Parent 
{ 
    public Parent() 
    { 
     Init(); 
    } 

    protected void Init() 
    { 
     Console.WriteLine("Parent ctor()"); 
    } 

    public Parent(int i) 
    { 
     Init(i); 
    } 

    protected void Init(int i) 
    { 
     Console.WriteLine("Parent ctor(int)"); 
    } 
} 

public class Child : Parent 
{ 
    public Child() 
    { 
     Init(); 
    } 

    protected void Init() 
    { 
     Console.WriteLine("Child ctor()"); 
    } 

    public Child(int i) 
    { 
     Init(i); 
     base.Init(i); 
     Init(); 
    } 


    protected void Init(int i) 
    { 
     Console.WriteLine("Child ctor(int)"); 
    } 

} 

然後這裏是一個辦法,你可以做到這一點,我真的不建議,但無論如何,我會它包含:

public class Parent 
{ 
    public Parent() 
    { 
     Console.WriteLine("Parent ctor()"); 
    } 

    public Parent(int i) 
    { 
     Console.WriteLine("Parent ctor(int)"); 
    } 
} 

public class Child : Parent 
{ 
    private static int _i; //this is likely to blow up at some point. 

    public Child() : base(_i) 
    { 
     Console.WriteLine("Child ctor()"); 
    } 

    public Child(int i) : this() 
    { 
     _i = i; 
     Console.WriteLine("Child ctor(int)"); 
    } 
} 
+0

希望這些可以幫助你。我正在收藏這本書,因爲我很好奇看到你想出什麼。可以肯定的是,這是一個奇怪的問題。 – 2012-07-27 18:42:23

+0

在最後一個例子中,我認爲靜態變量在調用Child無參數構造函數之前不會被設置。你測試過了嗎? – Sam 2012-07-27 19:06:35

+0

哈哈......你說得對。無論哪種方式,我認爲你無論如何都無法得到你想要的訂單,因爲它不會首先執行子控制器。父母將始終開火。 – 2012-07-27 19:56:25