程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C# Object Initialization[完整版]

C# Object Initialization[完整版]

編輯:關於C#

原文地址:http://www.csharp411.com/c-object-initialization/

當構造一個C#對象時,理解對象的作用域和構造器被初始化的序列是很重要的

Derived static fields

Derived static constructor

Derived instance fields

Base static fields

Base static constructor

Base instance fields

Base instance constructor

Derived instance constructor

示例

下面的是一個C#控制台程序的例子,這個例子演示了對象初始化的次序

這個程序創建基對象的派生對象,包含了靜態化和實例化構造器以及作用域,兩個作用域"Field1"和"Field2"在他們的定義裡被初始化,然而 "Field3"在構造器裡被初始化.同時也包含了一個證明為什麼不能從構造器裡調用虛方法的虛方法.當每個作用域和構造器被初始化時就會寫入控制台,因此你可以看到初始化的序列

using System;

namespace ObjectInit
{
  class Program
  {
    static void Main( string[] args )
    {
      Derived d = new Derived();
      Console.ReadLine();
    }
  }
  class Base
  {
    public Base()
    {
      Console.WriteLine( "Base.Instance.Constructor" );
      this.m_Field3 = new Tracker( "Base.Instance.Field3″ );
      this.Virtual();
    }
    static Base()
    {
      Console.WriteLine( "Base.Static.Constructor" );
    }
    private Tracker m_Field1 = new Tracker( "Base.Instance.Field1″ );
    private Tracker m_Field2 = new Tracker( "Base.Instance.Field2″ );
    private Tracker m_Field3;
    static private Tracker s_Field1 = new Tracker( "Base.Static.Field1″ );
    static private Tracker s_Field2 = new Tracker( "Base.Static.Field2″ );
    virtual public void Virtual()
    {
      Console.WriteLine( "Base.Instance.Virtual" );
    }
  }
  class Derived : Base
  {
    public Derived()
    {
      Console.WriteLine( "Derived.Instance.Constructor" );
      this.m_Field3 = new Tracker( "Derived.Instance.Field3″ );
    }
    static Derived()
    {
      Console.WriteLine( "Derived.Static.Constructor" );
    }
    private Tracker m_Field1 = new Tracker( "Derived.Instance.Field1″ );
    private Tracker m_Field2 = new Tracker( "Derived.Instance.Field2″ );
    private Tracker m_Field3;
    static private Tracker s_Field1 = new Tracker( "Derived.Static.Field1″ );
    static private Tracker s_Field2 = new Tracker( "Derived.Static.Field2″ );
    override public void Virtual()
    {
      Console.WriteLine( "Derived.Instance.Virtual" );
    }
  }
  class Tracker
  {
    public Tracker( string text )
    {
      Console.WriteLine( text );
    }
  }
}

下面就是來自這個示例程序的控制台輸出

Derived.Static.Field1
Derived.Static.Field2
Derived.Static.Constructor
Derived.Instance.Field1
Derived.Instance.Field2
Base.Static.Field1
Base.Static.Field2
Base.Static.Constructor
Base.Instance.Field1
Base.Instance.Field2
Base.Instance.Constructor
Base.Instance.Field3
Derived.Instance.Virtual
Derived.Instance.Constructor
Derived.Instance.Field3

2個階段的構建

注意在C#對象初始化的問題中還有個潛在的圈套。當初始化以派生對象開始轉到基類對象時,構造函數以相反次序進行初始化,先執行基類構造函數,再執行派生函數。

當你試圖通過基構造函數調用一個虛方法時,上述情況就會發生。因為派生構造函數還未被執行,所以當虛方法通過基類函數執行時,派生對象或許就不會完全初始化。

正如在案例程序顯示的那樣,當基構造函數調用虛方法時(程序輸出顯示:Derived.Instance.Virtual),由於派生構造函數未被執行,派生對象的Field3並未被初始化。如果虛方法是建立在一個需要被初始化的Field3,此時程序將出錯。

因此,你不能在對象函數中使用虛方法。而是在你第一次構建對象處執行“2個階段的構建”,此時再使用虛方法,如下:

Derived d = new Derived();

d.Virtual();

C#對象初始化提示:

一些關於C#對象初始化的一般規則和提示:

先變量後構造函數.變量先被初始化,然後構造函數被執行

先靜態化後實例化.當一個類被訪問時,靜態變量和構造函數最先被初始化.接著是對象的實例化變量和構造函數被初始化

先派生類後基類.對於變量和靜態構造函數,派生對象在基對象之前被初始化.比如C類派生自B類,B類派生自A類,那麼變量和靜態構造函數被初始化次序是C-B-A.

除了實例構造函數. 對於實例構造函數,基類構造函數在派生類構造函數之前執行,實例構造函數被執行次序是A-B-C.

不要假定變量的次序.Fields依據它們在源文件中的聲明的順序依次初始化.然而,自從程序員和工具可以隨意安排變量的聲明後,你不應該在依靠變量任何特別的次序初始化

對虛方法用兩個階段的構建.避免從一個構造器調用虛方法. 如果在初始化一個對象時需要調用一些虛方法,應在完整構造該對象的地方使用兩階段的構建,並隨後調用已構造對象的初始化方法。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved