VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • c# Object initialization 完整版

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  原文地址: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依据它们在源文件中的声明的顺序依次初始化.然而,自从程序员和工具可以随意安排变量的声明后,你不应该在依靠变量任何特别的次序初始化

   对虚方法用两个阶段的构建.避免从一个构造器调用虚方法. 如果在初始化一个对象时需要调用一些虚方法,应在完整构造该对象的地方使用两阶段的构建,并随后调用已构造对象的初始化方法。

 

 

  下面就是来自这个示例程序的控制台输出

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依据它们在源文件中的声明的顺序依次初始化.然而,自从程序员和工具可以随意安排变量的声明后,你不应该在依靠变量任何特别的次序初始化

   对虚方法用两个阶段的构建.避免从一个构造器调用虚方法. 如果在初始化一个对象时需要调用一些虚方法,应在完整构造该对象的地方使用两阶段的构建,并随后调用已构造对象的初始化方法。

 



相关教程