轉(zhuǎn)帖|其它|編輯:郝浩|2010-08-27 15:40:21.000|閱讀 703 次
概述:本文將圍繞c#靜態(tài)方法和實例方法討論一下。針對一些觀點,如:"靜態(tài)方法是常駐內(nèi)存", 還有"靜態(tài)方法比實例方法先裝載",做一個辨析。同時討論下何時用靜態(tài)方法,何時用實例方法。
# 界面/圖表報表/文檔/IDE等千款熱門軟控件火熱銷售中 >>
本文將圍繞c#靜態(tài)方法和實例方法討論一下。針對一些觀點,如:"靜態(tài)方法是常駐內(nèi)存", 還有"靜態(tài)方法比實例方法先裝載",做一個辨析。同時討論下何時用靜態(tài)方法,何時用實例方法。
前幾日,在微軟的好友發(fā)給我一個鏈接:《靜態(tài)方法和實例化方法之間的區(qū)別你知道了嘛? 歡迎討論!! - 問題最終 ...》,然后說這里某些觀點需要澄清一下,希望我寫一篇blog。我當時讀了這篇blog. 文比較短,列舉了靜態(tài)方法和實例方法的幾種案例,也沒有論點,然后就請大家討論。后面評論就比blog熱鬧多了。言辭也激烈,后來該blog作者干脆把這篇blog刪了。現(xiàn)在已經(jīng)看不到這篇blog了。現(xiàn)在我寫這篇blog,一是針對一些觀點做個辨析,二是完成好友的所托。
c#靜態(tài)方法和實例方法的幾種用法
見如下代碼:這三種形式我們應(yīng)該都用過。
- public class SomeClass
- {
- private string myfield = null;
- public static instance = new SomeClass();
- public instranceMethod() {};
- public static staticMethod() {};
- }
- public class AnotherClass
- {
- public static Main()
- {
- //第一種方式, 聲明實例,調(diào)用實例方法
- SomeClass someClass = new SomeClass();
- someClass.instanceMethod();
- //第二種方式,通過一個靜態(tài)的實例,去調(diào)用實例方法
- SomeClass.instance.instanceMethod();
- //第三種方式,直接調(diào)用靜態(tài)方法
- SomeClass.staticMethod();
- }
- }
這幾種方式在調(diào)用時間,還有線程安全,面向?qū)ο蟮木幊谭矫娑加胁顒e。后文會談到。
"靜態(tài)方法是常駐內(nèi)存"
這是那位blog作者在評論中給出的觀點。我覺得"靜態(tài)方法是常駐內(nèi)存"的說法是不對的。要知道一個.NET類型的靜態(tài)方法是屬于這個.NET類型的。而這個.NET類型是一個.NET 程序集的一部分。這個.NET程序集是被一個AppDomain裝入到內(nèi)存里面來的。這個AppDomain是可以從內(nèi)存卸載的。一個有.NET CLR的進程里面可以有多于一個的AppDomain,第一個AppDomain之后的AppDomain都可以動態(tài)創(chuàng)建和卸載。這些AppDomain中的.NET程序集,既可以有靜態(tài)方法,也可以有實例方法。不管是靜態(tài)方法還是實例方法,都是隨其程序集所在的AppDomain一起創(chuàng)建和卸載。第一個AppDomain在整個程序運行結(jié)束時也會最后被卸載。其中所含的.NET程序集自然也卸載。看圖1會更明白點。所以靜態(tài)方法不存在常駐內(nèi)存一說。
圖1
"靜態(tài)方法比實例方法先裝載"
這也是那篇blog的評論中某些人提出的觀點。我不知道他們的論據(jù)是什么,但是我已經(jīng)做過實驗,而且也寫過這兩篇blog關(guān)于.NET反射和metadata加載--致Jeffray Zhao等幾位和firelong和[繼續(xù)討論]關(guān)于Windows PE和.NET assembly的加載來證明.NET程序集的加載方式是整個地加載,而不是用到某個metadata才加載該metadata, 用到某個方法才加載該方法。因為靜態(tài)方法和實例方法同屬于一個.NET類型,而一個.NET類型屬于一個.NET程序集。在整個地加載一個.NET程序集的時候,不管是靜態(tài)方法還是實例方法,都隨該程序集全部加載進內(nèi)存。所以"靜態(tài)方法比實例方法先裝載"也是不成立的。
何時用靜態(tài)方法,何時用實例方法
先說實例方法,當你給一個類寫一個方法,如果該方法需要訪問某個實例的成員變量時,那么就將該方法定義成實例方法。一類的實例通常有一些成員變量,其中含有該實例的狀態(tài)信息。而該方法需要改變這些狀態(tài)。那么該方法需要聲明成實例方法。
靜態(tài)方法正好相反,它不需要訪問某個實例的成員變量,它不需要去改變某個實例的狀態(tài)。我們把該方法定義成靜態(tài)方法。
第一種方式, 聲明實例,調(diào)用實例方法
當一個類有多個實例,例如學(xué)生這個類,實例可以有學(xué)生甲,學(xué)生乙,學(xué)生丙,等等,我們就用第一種方式。在多線程的情況下,只要每個線程都創(chuàng)建自己的實例,那么第一種方法通常是線程安全的。
第二種方式,通過一個靜態(tài)的實例,去調(diào)用實例方法
這種情況比較特殊,通常是整個程序里該類唯一的一個實例,我們通過調(diào)用該實例的實例方法來改變該實例的某些狀態(tài)。這一個實例在多線程的情況下,通常是線程不安全的。除非我們給這個實例加鎖。防止其他線程訪問該實例。
第三種方式,直接調(diào)用靜態(tài)方法
這種情況下靜態(tài)方法不需要去改變某個實例的狀態(tài)。只要得到少量的參數(shù)就可完成既定事情。比如判斷一個文件是否存在,只要給個文件路徑和文件名,就能知道該文件是否存在。
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:網(wǎng)絡(luò)轉(zhuǎn)載