静态构造函数是在构造函数方法前面添加了static关键字之后形成的,并且没有修饰符(public,private),没有参数。
静态构造函数的特点:
- 静态构造函数没有修饰符修饰(public,private),因为静态构造函数不是我们程序员调用的,是由.net 框架在合适的时机调用的。
- 静态构造函数没有参数,因为框架不可能知道我们需要在函数中添加什么参数,所以规定不能使用参数。
- 静态构造函数前面必须是static 关键字。如果不加这个关键字,那就是普通的构造函数了。
- 静态构造函数的调用时机,是在类被实例化或者静态成员被调用的时候进行调用,并且是由.net框架来调用静态构造函数来初始化静态成员变量。
- 一个类中只能有一个静态构造函数。
- 无参数的静态构造函数和无参数的构造函数是可以并存的。
- 静态构造函数只会被执行一次。
- 就像如果没有在类中写构造函数,那么框架会为我们生成一个构造函数,那么如果我们在类中定义了静态变量,但是又没有定义静态构造函数,那么框架也会帮助我们来生成一个静态构造函数来让框架自身来调用。
现在我们通过一个实际的例子,验证静态构造函数的调用时机:
using System;
namespace ConsoleApp2
{
class Class20
{
static void Main(string[] args)
{
Console.WriteLine(A.strText);
Console.WriteLine(B.strText);
Console.Read();
}
}
public class A
{
public static string strText;
public string Text;
static A()
{
strText = "AAA";
Console.WriteLine("hi, static A");
}
public A()
{
Text = "AAAAAAAAAA";
Console.WriteLine("hi, A");
}
}
public class B : A
{
static B()
{
strText = "BBB";
Console.WriteLine("hi, static B");
}
public B()
{
Text = "BBBBBBBBB ";
Console.WriteLine("hi, B");
}
}
}
输出结果:
当调用A.strText时,因为strText是静态变量,.net框架会调用类的静态构造函数,打印AAA。
当调用B.strText时,因为strText是属于类A的静态变量,.net框架会调用类A的静态构造函数,但是静态构造函数只会被执行一次,所以,不会调用类A的静态构造函数,只会返回strText的值。
但是如果我们把输出更改一下,输出结果就大不一样了。
using System;
namespace ConsoleApp2
{
class Class20
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
Console.Read();
}
}
public class A
{
public static string strText;
public string Text;
static A()
{
strText = "AAA";
Console.WriteLine("hi, static A");
}
public A()
{
Text = "AAAAAAAAAA";
Console.WriteLine("hi, A");
}
}
public class B : A
{
static B()
{
strText = "BBB";
Console.WriteLine("hi, static B");
}
public B()
{
Text = "BBBBBBBBB ";
Console.WriteLine("hi, B");
}
}
}
输出结果:
实例化类A,先调用类A的静态构造函数,然后调用类A的无参构造函数。
实例化类B,先调用类B的静态构造函数,因为B继承自A,先调用类A的无参构造函数,然后调用类B的无参构造函数。
using System;
namespace StructScript
{
class Class2
{
public class A
{
public A(string str)
{
Console.WriteLine(str);
}
}
public class B
{
static A a1 = new A("a1");
A a2 = new A("a2");
static B()
{
a1 = new A("a3");
}
public B()
{
a2 = new A("a4");
}
}
public static void Main(string[] args)
{
B b = new B();
Console.ReadLine();
}
}
}
在调用类型B的代码之前,先执行B的静态构造函数。静态构造函数先初始化静态变量,再执行函数体内的语句。先后打印a1
,a3。
接下来执行B b = new B(),即调用B的构造函数,构造函数先初始化成员变量,再执行函数体内的语句。先后打印a2, a4。