c# 9.0新特性——模塊初始化器
作者:MarkKang
出處:https://www.cnblogs.com/markkang/
1 背景動機(jī)
關(guān)于模塊或者程序集初始化工作一直是C#的一個痛點(diǎn),微軟內(nèi)部外部都有大量的報(bào)告反應(yīng)很多客戶一直被這個問題困擾,這還不算沒有統(tǒng)計(jì)上的客戶。那么解決這個問題,還有基于什么樣的考慮呢?
- 在庫加載的時候,能以最小的開銷、無需用戶顯式調(diào)用任何接口,使客戶做一些期望的和一次性的初始化。
- 當(dāng)前靜態(tài)構(gòu)造函數(shù)方法的一個最大的問題是運(yùn)行時會對帶有靜態(tài)構(gòu)造函數(shù)的類型做一些額外的檢查。這是因?yàn)橐獩Q定靜態(tài)構(gòu)造函數(shù)是否需要被運(yùn)行所必須的一步,但是這個又有著顯著的開銷影響。
- 使源代碼生成器在不需要用戶顯式調(diào)用一些東西的情況下能運(yùn)行一些全局的初始化邏輯。
2 詳細(xì)設(shè)計(jì)
C# 9.0將模塊初始化器設(shè)計(jì)為一個Attribute,用這個Attribute來修飾進(jìn)行模塊初始化邏輯的方法,就實(shí)現(xiàn)了模塊初始化功能。這個Attribute被命名為ModuleInitializerAttribute,具體定義如下:
using System; namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class ModuleInitializerAttribute : Attribute { } }
如果要使用模塊初始化器,你只要將ModuleInitializerAttribute用在符合下面要求的方法上就可以了。
- 該方法必須使靜態(tài)的、無參的、返回值為void的函數(shù)。
- 該方法不能是泛型或者包含在泛型類型里
- 該方法必須是可從其所在模塊里訪問的。也就是說,方法的有效訪問符必須是internal或者public,不能是局部方法。
using System.Runtime.CompilerServices; class MyClass { [ModuleInitializer] internal static void Initializer() { // ... } }
被修飾為ModuleInitializerAttribute的靜態(tài)方法會被編譯器在編譯時,在全局的靜態(tài)構(gòu)造函數(shù)中生成此代碼調(diào)用。如果有多個被修飾為初始化器的函數(shù),則每個函數(shù)生成一個初始化器代碼調(diào)用,這些初始化器代碼調(diào)用代碼會按照一定的順序(類型名稱順序和代碼順序)生成。當(dāng)模塊在被加載時,全局靜態(tài)構(gòu)造函數(shù)開始執(zhí)行,從而完成模塊代碼初始化工作。
3 問題與最佳實(shí)踐
模塊初始化器與靜態(tài)構(gòu)造函數(shù)之間有著一定的關(guān)聯(lián)影響。因?yàn)槟K初始化器是一個靜態(tài)方法,因而其被調(diào)用執(zhí)行前,必然會引起其所處類型的靜態(tài)構(gòu)造函數(shù)的執(zhí)行。請參考下列示例:
static class ModuleInit { static ModuleInit() { //先執(zhí)行 Console.WriteLine("ModuleInit靜態(tài)構(gòu)造函數(shù) cctor"); } [ModuleInitializer] internal static void Initializer() { //在靜態(tài)構(gòu)造函數(shù)執(zhí)行后才執(zhí)行 Console.WriteLine("模塊初始化器"); } }
在一個模塊中指定多個模塊初始化器的時候,他們之間的順序也是一個值得注意的問題。以上這些問題的存在,就要求我們注意以下幾點(diǎn):
在指定了模塊初始化器的類型中,不要在靜態(tài)構(gòu)造函數(shù)中,寫與模塊初始化器中代碼有著順序依賴代碼,最好的就是不要使用靜態(tài)構(gòu)造函數(shù)。
多個模塊初始化器之間的代碼,也不要有任何依賴關(guān)系,保持各個初始化器代碼的獨(dú)立性。
4 結(jié)束語
日常開發(fā)中,我們通常需要在模塊初始化的時候,做一些前置性的準(zhǔn)備工作,以前常采用靜態(tài)構(gòu)造函數(shù)這種不具有全局性方法,局限性很大,現(xiàn)在,這些都得到了完美解決。
以上就是c# 9.0新特性——模塊初始化器的詳細(xì)內(nèi)容,更多關(guān)于c# 9.0新特性的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#使用ScrapySharp實(shí)現(xiàn)多線程下載操作
在現(xiàn)代互聯(lián)網(wǎng)應(yīng)用中,數(shù)據(jù)抓取是一個常見的需求,無論是為了數(shù)據(jù)分析、內(nèi)容聚合還是自動化測試,ScrapySharp 是一個基于 .NET 的輕量級、高性能的網(wǎng)頁抓取庫,本文將探討如何在 C# 中使用 ScrapySharp 實(shí)現(xiàn)多線程下載策略,需要的朋友可以參考下2024-08-08C#基于Mongo的官方驅(qū)動手?jǐn)]一個Super簡易版MongoDB-ORM框架
本文給大家分享C#基于Mongo的官方驅(qū)動手?jǐn)]一個簡易版MongoDB-ORM框架,是一款屬于super簡易版的,通過圖文的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-05-05C#連接SQL數(shù)據(jù)庫和查詢數(shù)據(jù)功能的操作技巧
本文給大家分享C#連接SQL數(shù)據(jù)庫和查詢數(shù)據(jù)功能的操作技巧,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-05-05WPF實(shí)現(xiàn)XAML轉(zhuǎn)圖片的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何利用WPF實(shí)現(xiàn)XAML轉(zhuǎn)圖片,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定幫助,感興趣的小伙伴可以了解一下2022-11-11