静态构造函数趣谈!
类的静态构造函数也叫类型构造器,静态构造器,他调用的时刻由CLR来控制:
CLR会选择如下时间之一来调用静态构造函数:
1,在类型的第一个实例创建之前,或类型的非继承字段或成员第一次访问之前。这里的“之前”,代表前后衔接的意思。这里的时刻是精确的!
2,在非继承的静态字段或成员第一次访问之前的某个时刻,具体时刻不定!
由于调用的时刻不确定,所以我们最好不要编写依赖于特定的静态构造函数的执行顺序的代码,这样很容易产生不可预料的后果!
下面大家看三个Demo,我们来更加深入的看看静态构造函数的一些有趣的行为:
Demo1:
static void Main(string[] args)
{
Console.WriteLine(B.strText);
}
public class A
{
public static string strText;
static A()
{
strText = "aaaa";
}
}
public class B : A
{
static B()
{
strText = "bbbb";
}
}
大家猜猜结果是什么,可能有人认为输出的是bbbb,因为访问B.strText需要调用B类的静态构造函数static B()。实际上输出的结果是aaaa,因为strText是类A的静态字段,而类B只是继承了这个字段,所以这里会调用类A的静态构造函数static A(),所以输出结果是aaaa。这也没有什么真正可说的,相信大家都能看出这个结果的。
下面看看第二个Demo:
Demo2:
static void Main(string[] args)
{
B b = new B();
A a = new A();
Console.WriteLine(B.strText);
}
public class A
{
public static string strText;
static A()
{
strText = "aaaa";
}
}
public class B : A
{
static B()
{
strText = "bbbb";
}
}
大家猜猜输出结果是什么,可能有人认为会输出aaaa,理由是new B()之前会调用static B(),然后new A()之前需要调用static A,这样结果是aaaa,但是实际情况并非如果,正确的结果是bbbb,原因如下:
在执行 new B(); 之前,B类的静态构造函数会调用,也就是会调用:
static B()
{
strText="bbbb";
}
当执行到strText=“bbbb"的时候,这时需要访问strText字段,而B的strText字段是从A类继承的,所以这里需要会先调用:
static A()
{
strText="aaaa";
}
执行这个函数以后strText的值是aaaa
然后代码又回到static B()中,这时才执行static B()中的strText="bbbb"这行,所以strText这时的值是bbbb
当执行A a=new A();的时候,不会在调用A的静态构造函数了,因为前面已经调用过了,静态函数在整个应用程序域的生命周期中只会调用一次!
请大家多指教啊!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· SQL Server 2025 AI相关能力初探
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库