类中的static成员:

一、出现原因及作用:

  1、需要在一个类的各个对象间交互,即需要一个数据对象为整个类而非某个对象服务。

  2、同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。

  类的static成员满足了上述的要求,因为它具有如下特征:有独立的存储区,属于整个类。

二、注意:

  1、对于静态的数据成员,连接器会保证它拥有一个单一的外部定义。静态数据成员按定义出现的先后顺序依次初始化,注意静态成员嵌套时,要保证所嵌套的成员已经初始化了。消除时的顺序是初始化的反顺序。

  2、类的静态成员函数是属于整个类而非类的对象,所以它没有this指针,这就导致了它仅能访问类的静态数据和静态成员函数。

const 是c++中常用的类型修饰符,但我在工作中发现,许多人使用它仅仅是想当然尔,这样,有时也会用对,但在某些微妙的场合,可就没那么幸运了,究其实质原由,大多因为没有搞清本源。故在本篇中我将对const进行辨析。溯其本源,究其实质,希望能对大家理解const有所帮助,根据思维的承接关系,分为如下几个部分进行阐述。

静态构造函数:
1)用于对静态字段、只读字段等的初始化。       
(2)添加static关键字,不能添加访问修饰符,因为静态构造函数都是私有的。    
(3)类的静态构造函数在给定应用程序域中至多执行一次:只有创建类的实例或者引用类的任何静态成员才激发静态构造函数
(4)静态构造函数是不可继承的,而且不能被直接调用。      
(5)如果类中包含用来开始执行的 Main 方法,则该类的静态构造函数将在调用 Main 方法之前执行。  
    任何带有初始值设定项的静态字段,则在执行该类的静态构造函数时,先要按照文本顺序执行那些初始值设定项。 
(6)如果没有编写静态构造函数,而这时类中包含带有初始值设定的静态字段,那么编译器会自动生成默认的静态构造函数。

首先,静态构造函数不代表你不可以构造这个类。所谓静态构造函数就是在这个类第一次被使用之前首先进行初始化,其目的仅仅是做一些必要的初始化,例如静态变量。

其次,如果你没有写一个非静态的构造函数,系统会帮你写一个出来的,也就是会默认构造一个出来的。

此外,所有静态非常量字段实际上都会在静态构造函数里面进行赋值,所有非静态非常量字段实际上都会在非静态构造函数里面进行赋值。

构造函数,静态构造函数与继承链
在.net的类中,如果没有给类添加任何构造函数,编译器将会给类自动添加一个默认构造函数,它的作用

就是初始化该类的字段为默认值。构造函数在继承链中的层次结构的执行顺序是由上到下进行,从System

.Object开始到要实例化的类为止。

1,静态构造函数
在.net中静态构造函数的作用就是初始化类中的静态字段,静态构造函数不需访问修饰符,也不能带任何

参数,可以与无参数的构造函数共存,同时静态构造函数是由.net运行时调用的,而不能在程序中调用,

 静态构造函数自动被调用,不能被显式调用。虽然提供了许多约束条件,但是静态构造函数执行的确切时间和顺序是不确定的:
一个类的静态构造函数在这个类的任何实例被创建前执行。
一个类的静态构造函数在类的任何静态成员被引用前执行。
一个类的静态构造函数在它的所有派生类的静态构造函数执行之后执行。
一个类的静态构造函数从不会被执行一次以上。
如果一些操作只希望被执行一次。这时候就可以考虑使用静态构造函数。当然如果设计的面向对象一些的话,那就是使用单件模式了。

静态构造函数可以在第一次调用静态类的任何方法、属性时自动调用,所以在静态构造函数里抛出的异常捕获比较麻烦。

C#的一个新特征是也可以给类编写无参数的静态构造函数。这种构造函数只执行一次,而前面的构造函数是实例构造函数,只要创建类的对象,它都会执行。静态构造函数在C++和VB6中没有对应的函数。

class MyClass
{
   static MyClass()
   {
      // initialization code
   }
   // rest of class definition
}

编写静态构造函数的一个原因是,类有一些静态字段或属性,需要在第一次使用类之前,从外部源中初始化这些静态字段和属性。

.NET运行库没有确保静态构造函数什么时候执行,所以不要把代码放在某个特定的时刻(例如,加载程序集时)执行的静态构造函数中。也不能预计不同类的静态构造函数按照什么顺序执行。但是,可以确保静态构造函数至多运行一次,即在代码引用类之前执行。在C#中,静态构造函数通常在第一次调用类的成员之前执行。

注意,静态构造函数没有定义访问修饰符,其他C#代码从来不调用它,但在加载类时,总是由.NET运行库调用它,所以像public 和 private这样的访问修饰符就没有意义了。同样,静态构造函数不能带有任何参数,一个类也只能有一个静态构造函数。很显然,静态构造函数只能访问类的静态成员,不能访问实例成员。

注意,无参数的实例构造函数可以在类中与静态构造函数安全共存。尽管参数列表是相同的,但这并不矛盾,因为静态构造函数是在加载类时执行,而实例构造函数是在创建实例时执行,所以构造函数的执行不会有冲突。

如果多个类都有静态构造函数,先执行哪个静态构造函数是不确定的。此时应根据其他静态构造函数的执行情况,在静态构造函数中添加代码。另一方面,如果静态字段有默认值,它们就在调用静态构造函数之前指定。

下面用一个例子来说明静态构造函数的使用。假定这个例子叫StaticConstructor,基于包含用户设置的程序(假定存储在某个配置文件中)。为了简单一些,假定只有一个用户设置——BackColor,表示要在应用程序中使用的背景色。因为这里不想编写从外部数据源中读取数据的代码,所以假定该设置在工作日的背景色是红色,在周末的背景色是绿色。程序仅在控制台窗口中显示设置—— 但这足以说明静态构造函数是如何工作的。

namespace Wrox.ProCSharp.StaticConstructorSample
{
   public class UserPreferences
   {
      public static readonly Color BackColor;
 
 
      static UserPreferences()
      {
         DateTime now = DateTime.Now;
         if (now.DayOfWeek == DayOfWeek.Saturday
            || now.DayOfWeek == DayOfWeek.Sunday)
            BackColor = Color.Green;
         else
            BackColor = Color.Red;
      }
 
 
      private UserPreferences()
      {
      }
   }
}

这段代码说明了颜色设置如何存储在静态变量中,该静态变量在静态构造函数中进行初始化。把这个字段声明为只读类型,表示其值只能在构造函数中设置。本章后面将详细介绍只读字段。这段代码使用了Microsoft在Framework类库中支持的两个有用的结构System.DateTime和System.Drawing.Color。DateTime结构实现了静态属性Now和实例属性DayOfWeek,Now属性返回当前的时间,DayOfWeek属性可以计算出某个日期是星期几。Color(详见第20章)用于存储颜色,它实现了各种静态属性,例如本例使用的Red和Green,返回常用的颜色。为了使用Color结构,需要在编译时引用System.Drawing.dll程序集,且必须为System.Drawing命名空间添加一个using语句:

using System;
using System.Drawing;

用下面的代码测试静态构造函数:

class MainEntryPoint
   {
      static void Main(string[] args)
      {
         Console.WriteLine("User-preferences: BackColor is: " +
                            UserPreferences.BackColor.ToString());
      }
   }

编译并运行这段代码,会得到如下结果:

C:>StaticConstructor
User-preferences: BackColor is: Color [Red]