本文將圍繞c#靜態方法和實例方法討論一下針對一些觀點如靜態方法是常駐內存 還有靜態方法比實例方法先裝載做一個辨析同時討論下何時用靜態方法何時用實例方法
前幾日在微軟的好友發給我一個鏈接《靜態方法和實例化方法之間的區別你知道了嘛? 歡迎討論!! 問題最終 》然後說這裡某些觀點需要澄清一下希望我寫一篇blog我當時讀了這篇blog 文比較短列舉了靜態方法和實例方法的幾種案例也沒有論點然後就請大家討論後面評論就比blog熱鬧多了言辭也激烈後來該blog作者干脆把這篇blog刪了現在已經看不到這篇blog了現在我寫這篇blog一是針對一些觀點做個辨析二是完成好友的所托
c#靜態方法和實例方法的幾種用法
見如下代碼這三種形式我們應該都用過
view sourceprint? public class SomeClass
{
private string myfield = null;
public static instance = new SomeClass();
public instranceMethod() {};
public static staticMethod() {};
}
public class AnotherClass
{
public static Main()
{
//第一種方式 聲明實例調用實例方法
SomeClass someClass = new SomeClass();
someClassinstanceMethod();
//第二種方式通過一個靜態的實例去調用實例方法
SomeClassinstanceinstanceMethod();
//第三種方式直接調用靜態方法
SomeClassstaticMethod();
}
}
這幾種方式在調用時間還有線程安全面向對象的編程方面都有差別後文會談到
靜態方法是常駐內存
這是那位blog作者在評論中給出的觀點我覺得靜態方法是常駐內存的說法是不對的要知道一類型的靜態方法是屬於這類型的而這類型是一 程序集的一部分這程序集是被一個AppDomain裝入到內存裡面來的這個AppDomain是可以從內存卸載的一個 CLR的進程裡面可以有多於一個的AppDomain第一個AppDomain之後的AppDomain都可以動態創建和卸載這些AppDomain中程序集既可以有靜態方法也可以有實例方法不管是靜態方法還是實例方法都是隨其程序集所在的AppDomain一起創建和卸載第一個AppDomain在整個程序運行結束時也會最後被卸載其中所含程序集自然也卸載看圖會更明白點所以靜態方法不存在常駐內存一說
圖
靜態方法比實例方法先裝載
這也是那篇blog的評論中某些人提出的觀點我不知道他們的論據是什麼但是我已經做過實驗而且也寫過這兩篇blog關反射和metadata加載致Jeffray Zhao等幾位和firelong和[繼續討論]關於Windows assembly的加載來證程序集的加載方式是整個地加載而不是用到某個metadata才加載該metadata 用到某個方法才加載該方法因為靜態方法和實例方法同屬於一類型而一類型屬於一程序集在整個地加載一程序集的時候不管是靜態方法還是實例方法都隨該程序集全部加載進內存所以靜態方法比實例方法先裝載也是不成立的
何時用靜態方法何時用實例方法
先說實例方法當你給一個類寫一個方法如果該方法需要訪問某個實例的成員變量時那麼就將該方法定義成實例方法一類的實例通常有一些成員變量其中含有該實例的狀態信息而該方法需要改變這些狀態那麼該方法需要聲明成實例方法
靜態方法正好相反它不需要訪問某個實例的成員變量它不需要去改變某個實例的狀態我們把該方法定義成靜態方法
第一種方式 聲明實例調用實例方法
當一個類有多個實例例如學生這個類實例可以有學生甲學生乙學生丙等等我們就用第一種方式在多線程的情況下只要每個線程都創建自己的實例那麼第一種方法通常是線程安全的
第二種方式通過一個靜態的實例去調用實例方法
這種情況比較特殊通常是整個程序裡該類唯一的一個實例我們通過調用該實例的實例方法來改變該實例的某些狀態這一個實例在多線程的情況下通常是線程不安全的除非我們給這個實例加鎖防止其他線程訪問該實例
第三種方式直接調用靜態方法
這種情況下靜態方法不需要去改變某個實例的狀態只要得到少量的參數就可完成既定事情比如判斷一個文件是否存在只要給個文件路徑和文件名就能知道該文件是否存在
From:http://tw.wingwit.com/Article/program/net/201311/11604.html