C# const謹慎使用!

  • 539
  • 0
  • C#
  • 2020-01-08

在寫Library時,要特別注意使用const。

為什麼要說小心使用呢? 因為如果不清楚特性,則可能導致程式明明改好了,也上版了,但結果還是不如預期。

「const」屬於「編譯時期常數」,只能在宣告中初始化,在編譯的時候,就會決定值。且由於編譯器會傳播常數,所以其他應用程式或是函式庫有使用這個常數,都會固定其值。再換句話說,哪一天改了這個常數值,所有引用到這個dll的,都要用這個異動後的dll連同專案再次重新編譯,不能只單純的將dll更新到應用程式的bin目錄。這樣在上版的時候頗為麻煩,這個不方便感,講浮誇一點,當電腦換了一個RAM後,還要重灌才能用的感覺…

「readonly」屬於「執行時期常數」,能在建構函式或宣告中初始化,在程式執行階段,才會決定值。基於不是很確定未來會不會改的變數,通常都會改使用readonly。

因此const雖然效能比readonly好,但維護性上,readonly更勝一籌,在使用上要多考量,避免踩坑。

測試

先建立一個類別庫【HelpLib】,裡頭有一個SomeHelper,並對外公開一個int常數,其值為「1」

接著再建立一個主控台應用程式【MyConsole】。
我們將HelpLib的專案編譯後,將dll放到此【MyConsole】裡,並將其加入參考。
接著將SomeHelper.Num輸出。

接著編譯【MyConsole】,再到bin目錄找MyConsole.exe,直接執行,結果如下。

接著因為需求調整,這個Num常數必須變成100,按正常的邏輯,就只會更新HelpLib.dll。
因此動手來更新吧~

然後我們就把HelpLib.dll直接更新到【MyConsole】的bin目錄。

再執行MyConsole.exe,結果如下,還是「1」,不是修改後的「100」。

我們用JetBrain dotPeek開啟MyConsole.dll 。(因為筆者使用.NET Core,所以要看的是MyConsole.dll,如果是使用.NET Framework,要看.exe)
觀察一下反組譯的結果與IL Code,呼叫HelpLib.SomeHelper.Num的地方,其實已經固定了常數「1」了,而這個「1」是當時使用舊的HelpLib.dll編譯決定的。

所以,要能正常取得更新後的值,就要將新的HelpLib.dll與MyConsole專案,一起重新編譯
重新編譯後,再重新執行一次,就會是預期的結果了。

再看一下反組譯的結果與IL Code,,固定常數已變成「100」了。

結論

若您本身開發的是dll要給別人使用,或是給很多專案使用,假若無法保證此值不會異動,建議對外公開的變數使用readonly來初始值。免得到時候更改了常數,而各專案有使用到的,都要配合此dll再次重新編譯。

參考資料:const 關鍵字

 

創用 CC 授權條款
本著作由Chenting Weng製作,以創用CC 姓名標示 4.0 國際 授權條款釋出。
This work by Chenting Weng is licensed under a Creative Commons Attribution 4.0 International License.
Based on a work at https://dotblogs.com.tw/chentingw.

部分文章內容會引用到其他網站的簡介或圖片,若有侵犯到您的著作權,請留言告知,本人會儘快移除。
免責聲明:文章屬個人記事使用,僅供參考,若引用文章造成一切損失,本人不承擔任何責任。如有錯誤,歡迎留言告知。

Part of the content of the article will refer to the profile or picture of other websites.
If there is any infringement of your copyright, please leave a message and let me remove it as soon as possible.
Disclaimer:The article is for personal use and is for reference only. I will not bear any responsibility for any loss caused by quoting the article. If there is an error, please leave a message to inform.