2013-07-10 80 views
3

下面的C#代碼不能編譯。基礎構造函數調用的靜態是什麼?

public class BaseType 
{ 
    public BaseType(int bar) 
    { 
     // Do stuff with bar... 
    } 
} 

public class DerivedType : BaseType 
{ 
    private int foo; 

    public DerivedType() : base(foo = 0) {} 
} 

錯誤發生在調用DerivedType的基本構造,與消息「不能在靜態情況下訪問非靜態字段‘富’。」這個錯誤信息告訴我什麼? 'foo'不是靜態的,類也不是,它們也不是靜態的構造函數。

+0

我不認爲它的精確複製,但是這是一個非常有用的鏈接,謝謝@mikez。 – Drake

回答

6

在指出base(foo = 0)執行DerivedType類尚未「創建」,因此它無法訪問它定義的成員。

事情發生的順序是這樣的

  1. 用戶來電new DerivedType()
  2. 該代碼調用DerivedType的base(foo = 0)
  3. 該代碼調用BASETYPE的隱含base()Object()
  4. 內存爲Object任何領域被分配,然後Object()構造函數運行完成。
  5. 分配BaseType中的任意字段的內存,然後運行BaseType(int bar)構造函數以完成。
  6. 分配DerivedType中的任何字段的內存,然後構造函數運行完成。

所以你看,你正試圖值在步驟2中分配給foo,但foo將不存在,直到第6步

4

問題是構造函數尚未運行。

在基本類型構建之前,您無法訪問您的實例。

+0

我喜歡你說這句話的方式!錯誤的奇怪部分是它在實例外發生的事情是一個靜態的上下文。 – 2013-07-10 01:01:13

+0

從技術上講,您可以在基礎構造函數完成之前訪問實例字段:在基類中創建一個虛擬方法,並從基礎構造函數中調用該方法,並在訪問該實例字段的派生類中重寫。 – fcuesta

+0

@fcuesta:是的,但基礎構造函數將有_started_。 – SLaks

3

錯誤提示foo不是靜態的,但只有類的靜態成員和構造函數本身的參數可用於調用基礎構造函數(除了其他外部常量)。

你大概的意思

public DerivedType() : base(0) { 
    foo = 0;  
} 

要在C#中的文件摘錄非常精確如下:部分C#5.0規範的10.11.1 「構造函數初始化」。

訪問構造函數的參數本身允許:

通過一個實例構造函數聲明的形式參數列表給出的參數的範圍包括那個聲明的構造函數初始化。因此,允許構造函數初始化器訪問構造函數的參數。

但獲得的實例,因此實例字段是不允許的:

實例構造函數初始化不能訪問被創建的實例。因此,在構造函數初始值設定項的參數表達式中引用此錯誤時,編譯時會出錯,因爲它是通過簡單名稱引用任何實例成員的參數表達式的編譯時錯誤

+0

是的;他在問_why_。 – SLaks

+0

@SLaks - 我已經添加了C#規範的限制。我對「爲什麼這樣設計」(這通常在SO範圍之外)沒有任何見解,對我來說也有一些限制。 –

+0

@AlexeiLevenkov看到Eric Lippert在可能與我聯繫的答案中的答案。它解釋了爲什麼這種語言是這樣設計的。 –

相關問題