2011-09-27 128 views
42

我需要從另一個主體調用一個構造函數,該怎麼做?C#從另一個主體調用一個構造函數

基本上

class foo { 
    public foo (int x, int y) 
    { 
    } 

    public foo (string s) 
    { 
     // ... do something 

     // call another constructor 
     this (x, y); // doesn't work 
     foo (x, y); // neither 
    } 
} 
+0

如何像公共富(INT X,INT Y,字符串s) –

回答

61

你不能。

你必須找到一種方法,鏈構造函數,如:

public foo (int x, int y) { } 
public foo (string s) : this(XFromString(s), YFromString(s)) { ... } 

或移動建設的代碼放到一個常見的設置方法,像這樣:

public foo (int x, int y) { Setup(x, y); } 
public foo (string s) 
{ 
    // do stuff 
    int x = XFromString(s); 
    int y = YFromString(s); 
    Setup(x, y); 
} 

public void Setup(int x, int y) { ... } 
+11

請注意,一般來說,setup方法將無法寫入'readonly'變量,但構造函數可以將'readonly'變量作爲'ref'參數傳遞給setup方法,然後該方法可以寫入其'ref即使它們是隻讀變量也是如此。 – supercat

+5

安裝方法在大多數情況下應該是私人的 –

+0

請注意,在第一種解決方案中,「XFromString」和「YFromString」必須是靜態方法。這是我最喜歡的方式! – AxelWass

6

同時調用基地和這個類的構造函數明確你需要使用如下的語法(注意,在C#中,你不能使用它在C初始化領域,如++):

class foo 
{ 
    public foo (int x, int y) 
    { 
    } 

    public foo (string s) : this(5, 6) 
    { 
     // ... do something 
    } 
} 

//編輯:注意到,你在樣本中使用了x,y。當然,以這種方式調用ctor時給出的值不能依賴於其他構造函數的參數,它們必須以其他方式解決(儘管如上面的編輯代碼示例,它們不需要是常量)。如果xys計算,你可以這樣來做:

 
public foo (string s) : this(GetX(s), GetY(s)) 
+2

小此言一個構造函數:public FOO(字符串s):這個(X,Y)將無法正常工作。public foo(string s,int x,int y):this(x,y)會編譯 –

+0

當然,我的不好。固定。感謝您指出這一點 –

29

this(x, y)是正確的,但它必須是構造函數體開始之前:

public Foo(int x, int y) 
{ 
    ... 
} 

public Foo(string s) : this(5, 10) 
{ 
} 

需要注意的是:

  • 您只能鏈到一個構造函數,無論是thisbase - 即構造函數可以鏈ANOT她的,當然。
  • 在執行構造函數體中的任何代碼後,您無法鏈接到構造函數
  • 你不能在其他構造函數的參數中使用this,包括調用實例方法 - 但你可以調用靜態方法。
  • 在鏈接調用之前執行的任何實例變量初始值設定項都是

我在我的article about constructor chaining中獲得了更多信息。

+0

當你有這樣的事情時,這是特別惱人的:'class A {public A(IEnumerable items){...} public A(MyClass c):this(c.Items){... }}。在第二個ctor中的任何空檢查只會在訪問「c」後執行。如果c爲null,第二個ctor將拋出一個NRE,而不是首選的'ArgumentNullException'。如果你想讓你的領域只讀,除了在兩個地方實現相同的邏輯,沒有其他的可能性。或*是*有更好的方法來做到這一點? –

+2

@DanielHilgarth:是的。有一個通用的擴展方法來檢查無效性,否則返回原始值。然後你可以做'this(c.ThrowIfNull(「c」)。Items)' –

+0

謝謝,那也是我唯一能想到的。只是想編輯我的評論...不知道它是否是一種好方法,因爲我到目前爲止還沒有看到它...... –

1

,我就遇到了這個問題,一兩次自己...我落得必須做的是將我在其他構造函數中需要的任何邏輯提取到private void方法中,並在兩個地方調用它。

class foo 
{ 
    private void Initialize(int x, int y) 
    { 
    //... do stuff 
    } 

    public foo(int x, int y) 
    { 
    Initialize(x, y); 
    } 

    public foo(string s_ 
    { 
    // ... do stuff 

    Initialize(x, y) 
    // ... more stuff 
    } 
} 
相關問題