博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

关于C#静态构造函数的几点说明

Posted on 2008-01-03 16:20  aming  阅读(457)  评论(1编辑  收藏  举报
  静态构造函数是C#的一个新特性,其实好像很少用到。不过当我们想初始化一些静态变量的时候就需要用到它了。这个构造函数是属于类的,而不是属于哪里实例的,就是说这个构造函数只会被执行一次。也就是在创建第一个实例或引用任何静态成员之前,由.NET自动调用。
  
class SimpleClass
{
    
// Static constructor
    static SimpleClass()
    {
        
//
    }
}

  在使用静态构造函数的时候应该注意几点:

  1、静态构造函数既没有访问修饰符,也没有参数。因为是.NET调用的,所以像public和private等修饰符就没有意义了。
  
  2、是在创建第一个类实例或任何静态成员被引用时,.NET将自动调用静态构造函数来初始化类,也就是说我们无法直接调用静态构造函数,也就无法控制什么时候执行静态构造函数了。

  3、一个类只能有一个静态构造函数。

  4、无参数的构造函数可以与静态构造函数共存。尽管参数列表相同,但一个属于类,一个属于实例,所以不会冲突。

  5、最多只运行一次。

  6、静态构造函数不可以被继承。

  7、如果没有写静态构造函数,而类中包含带有初始值设定的静态成员,那么编译器会自动生成默认的静态构造函数。
 
本单元的内容基本上讲完了,现在说说静态成员最主要的一个应用“Singleton”,就是保证此类型的对象唯一性。其实实现很简单,如下就举一个简单的例子。

public class MySingleton
{
 private static readonly MySingleton _theOneAndOnly;
 static MySingleton()
 {
  _theOneAndOnly = new MySingleton();
 }
 public static MySingleton TheOnly
 {
  get{ return _theOneAndOnly; }
 }

 /// <summary>
 /// Private constructor to avoid object created from outside
 /// </summary>

 private MySingleton()
 {}
}

  对于静态成员何时被初始化,其实仔细看我上一个单元所说的对象构造步骤就可以分析出来。可能看起来比较抽象,尤其在分析嵌套关系的时候,现在就举一个例子来进行说明。

class A
{
 public static int X = B.Y;
 static A()
 {
  ++X;
 }
}

class B
{
 public static int Y = A.X;
 static B()
 {
  ++Y;
 }
}

  那么大家先猜猜如下调用输出结果是什么。

Debug.WriteLine( A.X.ToString() );
Debug.WriteLine( B.Y.ToString() );

  其结果是“2,1”,也就是A.X的值为2,而B.Y的值为1。

  分析此类问题,只要记住三点就行了。
  
  第一代码的执行顺序,代码在前的先执行;

  第二静态成员初始化语句要先于静态构造函数执行;

  第三静态成员初始化语句与静态构造函数只执行一次。

  如果了解这三点,接下来就分析为什么会出现上面的结果。

  当调用到第一条语句的时候,

Debug.WriteLine( A.X.ToString() );

  首先是访问A这个类型,那么要对A这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。

  对于A的静态成员只有“X”,按照上一单元的过程,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。

  那么它的成员初始化语句是“X = B.Y”,那么需要访问“B.Y”来初始化X这个静态成员。

  对于“B.Y”的访问,就是访问B类型,也是和访问A一样,首先对这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。而B的静态成员只有“Y”,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。

  那么对于“Y = A.X”成员初始化语句,由于此时不是第一次访问类型A,所以不再进行静态成员初始化和静态构造函数的调用,对于“A.X”的访问是直接访问。此时“A.X”的值为0,那么Y的值也为0;接着执行B的静态构造函数,这样处理后Y的值为1。

  那么对于A中的成员初始化语句“X = B.Y”,到此就执行完了,此时A类型中的X与B类型中的Y都是一样的,值为1。不过B中的静态成员初始化语句和静态构造函数都执行过了,而A中的静态构造函数还未执行。因此经过A的静态构造函数处理,A的X值为2,这也就是最后显示的结果。