C#中靜態(tài)構(gòu)造函數(shù)的幾點(diǎn)說(shuō)明介紹
靜態(tài)構(gòu)造函數(shù)是C#的一個(gè)新特性,其實(shí)好像很少用到。不過(guò)當(dāng)我們想初始化一些靜態(tài)變量的時(shí)候就需要用到它了。這個(gè)構(gòu)造函數(shù)是屬于類的,而不是屬于哪里實(shí)例的,就是說(shuō)這個(gè)構(gòu)造函數(shù)只會(huì)被執(zhí)行一次。也就是在創(chuàng)建第一個(gè)實(shí)例或引用任何靜態(tài)成員之前,由.NET自動(dòng)調(diào)用。
class SimpleClass
{
// Static constructor
static SimpleClass()
{
//
}
}
在使用靜態(tài)構(gòu)造函數(shù)的時(shí)候應(yīng)該注意幾點(diǎn):
1、靜態(tài)構(gòu)造函數(shù)既沒(méi)有訪問(wèn)修飾符,也沒(méi)有參數(shù)。因?yàn)槭?NET調(diào)用的,所以像public和private等修飾符就沒(méi)有意義了。
2、是在創(chuàng)建第一個(gè)類實(shí)例或任何靜態(tài)成員被引用時(shí),.NET將自動(dòng)調(diào)用靜態(tài)構(gòu)造函數(shù)來(lái)初始化類,也就是說(shuō)我們無(wú)法直接調(diào)用靜態(tài)構(gòu)造函數(shù),也就無(wú)法控制什么時(shí)候執(zhí)行靜態(tài)構(gòu)造函數(shù)了。
3、一個(gè)類只能有一個(gè)靜態(tài)構(gòu)造函數(shù)。
4、無(wú)參數(shù)的構(gòu)造函數(shù)可以與靜態(tài)構(gòu)造函數(shù)共存。盡管參數(shù)列表相同,但一個(gè)屬于類,一個(gè)屬于實(shí)例,所以不會(huì)沖突。
5、最多只運(yùn)行一次。
6、靜態(tài)構(gòu)造函數(shù)不可以被繼承。
7、如果沒(méi)有寫(xiě)靜態(tài)構(gòu)造函數(shù),而類中包含帶有初始值設(shè)定的靜態(tài)成員,那么編譯器會(huì)自動(dòng)生成默認(rèn)的靜態(tài)構(gòu)造函數(shù)。
靜態(tài)構(gòu)造函數(shù)趣談!
類的靜態(tài)構(gòu)造函數(shù)也叫類型構(gòu)造器,靜態(tài)構(gòu)造器,他調(diào)用的時(shí)刻由CLR來(lái)控制:
CLR會(huì)選擇如下時(shí)間之一來(lái)調(diào)用靜態(tài)構(gòu)造函數(shù):
1,在類型的第一個(gè)實(shí)例創(chuàng)建之前,或類型的非繼承字段或成員第一次訪問(wèn)之前。這里的“之前”,代表前后銜接的意思。這里的時(shí)刻是精確的!
2,在非繼承的靜態(tài)字段或成員第一次訪問(wèn)之前的某個(gè)時(shí)刻,具體時(shí)刻不定!
由于調(diào)用的時(shí)刻不確定,所以我們最好不要編寫(xiě)依賴于特定的靜態(tài)構(gòu)造函數(shù)的執(zhí)行順序的代碼,這樣很容易產(chǎn)生不可預(yù)料的后果!
下面大家看看以下的Demo,我們來(lái)更加深入的看看靜態(tài)構(gòu)造函數(shù)的一些有趣的行為:
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";
}
}
大家猜猜結(jié)果是什么,可能有人認(rèn)為輸出的是bbbb,因?yàn)樵L問(wèn)B.strText需要調(diào)用B類的靜態(tài)構(gòu)造函數(shù)static B()。實(shí)際上輸出的結(jié)果是aaaa,因?yàn)閟trText是類A的靜態(tài)字段,而類B只是繼承了這個(gè)字段,所以這里會(huì)調(diào)用類A的靜態(tài)構(gòu)造函數(shù)static A(),所以輸出結(jié)果是aaaa。這也沒(méi)有什么真正可說(shuō)的,相信大家都能看出這個(gè)結(jié)果的。
下面看看第二個(gè)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";
}
}
大家猜猜輸出結(jié)果是什么,可能有人認(rèn)為會(huì)輸出aaaa,理由是new B()之前會(huì)調(diào)用static B(),然后new A()之前需要調(diào)用static A,這樣結(jié)果是aaaa,但是實(shí)際情況并非如果,正確的結(jié)果是bbbb,原因如下:
在執(zhí)行 new B(); 之前,B類的靜態(tài)構(gòu)造函數(shù)會(huì)調(diào)用,也就是會(huì)調(diào)用:
static B()
{
strText="bbbb";
}
當(dāng)執(zhí)行到strText=“bbbb"的時(shí)候,這時(shí)需要訪問(wèn)strText字段,而B(niǎo)的strText字段是從A類繼承的,所以這里需要會(huì)先調(diào)用:
static A()
{
strText="aaaa";
}
執(zhí)行這個(gè)函數(shù)以后strText的值是aaaa
然后代碼又回到static B()中,這時(shí)才執(zhí)行static B()中的strText="bbbb"這行,所以strText這時(shí)的值是bbbb
當(dāng)執(zhí)行A a=new A();的時(shí)候,不會(huì)在調(diào)用A的靜態(tài)構(gòu)造函數(shù)了,因?yàn)榍懊嬉呀?jīng)調(diào)用過(guò)了,靜態(tài)函數(shù)在整個(gè)應(yīng)用程序域的生命周期中只會(huì)調(diào)用一次!
請(qǐng)大家多指教啊!
- C#構(gòu)造函數(shù)詳解
- C# 構(gòu)造函數(shù)如何調(diào)用虛方法
- 淺談C# 構(gòu)造方法(函數(shù))
- C#類繼承中構(gòu)造函數(shù)的執(zhí)行序列示例詳解
- C#中構(gòu)造函數(shù)和析構(gòu)函數(shù)用法實(shí)例詳解
- 詳解C#編程中構(gòu)造函數(shù)的使用
- C#靜態(tài)構(gòu)造函數(shù)用法實(shí)例分析
- C#私有構(gòu)造函數(shù)使用示例
- c#只讀字段和常量的區(qū)別,以及靜態(tài)構(gòu)造函數(shù)的使用實(shí)例
- C# 靜態(tài)構(gòu)造函數(shù)使用總結(jié)
- C#構(gòu)造函數(shù)在基類和父類中的執(zhí)行順序
相關(guān)文章
運(yùn)用示例簡(jiǎn)單講解C#取消令牌CancellationTokenSource
這篇文章運(yùn)用示例簡(jiǎn)單講解C#取消令牌CancellationTokenSource,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08