• C#中的静态构造函数(什么是静态构造函数)
  • 发布于 2个月前
  • 62 热度
    0 评论
静态构造函数用于初始化任何静态数据,或执行仅需执行一次的特定操作。 将在创建第一个实例或引用任何静态成员之前自动调用静态构造函数。
class SimpleClass
{
    // 静态变量必须在运行时初始化. www.duidaima.com
    static readonly long baseline;

    //静态构造函数只会执行一次
    static SimpleClass()
    {
        baseline = DateTime.Now.Ticks;
    }
}
静态构造函数具有以下属性:
1.静态构造函数不使用访问修饰符或不具有参数。
2.类或结构只能有一个静态构造函数。
3.静态构造函数不能继承或重载。
4.静态构造函数不能直接调用,并且仅应由公共语言运行时 (CLR) 调用。 可以自动调用它们。
5.用户无法控制在程序中执行静态构造函数的时间。

6.自动调用静态构造函数。 它在创建第一个实例或引用该类(不是其基类)中声明的任何静态成员之前初始化类。 静态构造函数在实例构造函数之前运行。 调用(而不是分配)分配给事件或委托的静态方法时,将调用类型的静态构造函数。 如果静态构造函数类中存在静态字段变量初始值设定项,它们将以在类声明中显示的文本顺序执行。 初始值设定项紧接着执行静态构造函数之前运行。


7.如果未提供静态构造函数来初始化静态字段,会将所有静态字段初始化为其默认值,如 C# 类型的默认值中所列。
8.如果静态构造函数引发异常,运行时将不会再次调用该函数,并且类型在应用程序域的生存期内将保持未初始化。 大多数情况下,当静态构造函数无法实例化一个类型时,或者当静态构造函数中发生未经处理的异常时,将引发 TypeInitializationException 异常。 对于未在源代码中显式定义的静态构造函数,故障排除可能需要检查中间语言 (IL) 代码。
9.静态构造函数的存在将防止添加 BeforeFieldInit 类型属性。 这将限制运行时优化。
10.声明为 static readonly 的字段可能仅被分配为其声明的一部分或在静态构造函数中。 如果不需要显式静态构造函数,请在声明时初始化静态字段,而不是通过静态构造函数,以实现更好的运行时优化。

11.运行时在单个应用程序域中多次调用静态构造函数。 该调用是基于特定类型的类在锁定区域中进行的。 静态构造函数的主体中不需要其他锁定机制。 若要避免死锁的风险,请勿阻止静态构造函数和初始值设定项中的当前线程。 例如,不要等待任务、线程、等待句柄或事件,不要获取锁定,也不要执行阻止并行操作,如并行循环、Parallel.Invoke 和并行 LINQ 查询。


 备注:尽管不可直接访问,但应记录显式静态构造函数的存在,以帮助故障排除初始化异常。

用法
1.静态构造函数的一种典型用法是在类使用日志文件且将构造函数用于将条目写入到此文件中时使用。
2.静态构造函数对于创建非托管代码的包装类也非常有用,这种情况下构造函数可调用 LoadLibrary 方法。

3.也可在静态构造函数中轻松地对无法在编译时通过类型参数约束检查的类型参数强制执行运行时检查。


示例
在此示例中,类 Bus 具有静态构造函数。 创建 Bus 的第一个实例 (bus1) 时,将调用该静态构造函数,以便初始化类。 示例输出验证即使创建了两个 Bus 的实例,静态构造函数也仅运行一次,并且在实例构造函数运行前运行。
public class Bus
{
    // 类的静态变量将被所有实例对象使用 www.duidaima.com
    //表示当天第一辆公共汽车开始其路线的时间。
    protected static readonly DateTime globalStartTime;

    // 车辆线路属性
    protected int RouteNumber { get; set; }

    // 用于初始化静态变量的静态构造函数。
    // 在运行第一个实例构造函数之前调用它。
    static Bus() //注意:静态构造函数不能有修饰符和参数
    {
        globalStartTime = DateTime.Now;
        Console.WriteLine("静态构造函数把全局的的开始时间设置为: {0}",
            globalStartTime.ToLongTimeString());
    }

    //实例构造函数.
    public Bus(int routeNum)
    {
        RouteNumber = routeNum;
        Console.WriteLine("#{0}号公交被创建.", RouteNumber);
    }

    // 实例方法.
    public void Drive()
    {
        TimeSpan elapsedTime = DateTime.Now - globalStartTime;
        Console.WriteLine("{0} is starting its route {1:N2} minutes after global start time {2}.",
                                this.RouteNumber,
                                elapsedTime.Milliseconds,
                                globalStartTime.ToShortTimeString());
    }
}

class TestBus
{
    static void Main()
    {
        // 创建此实例将激活静态构造函数。
        Bus bus1 = new Bus(71);

        // 创建第二辆公交.
        Bus bus2 = new Bus(72);

        // 第一辆公交开始出发
        bus1.Drive();

        // 等待第二辆公交出发
        System.Threading.Thread.Sleep(25);

        // 地二辆公交开始发车
        bus2.Drive();
        Console.WriteLine("输入任意按钮退出");
        Console.ReadKey();
    }
}
/* 案例输出结果:
    静态构造函数设置的全局开始时间为 3:57:08 PM.
    71路公交车被创建.
    72路公交车被创建
    71路公交将在6分钟后出发(3:57PM)
    72路公交将在31分钟后出发( 3:57 PM.)

*/

用户评论