const、readonly與static的整理
就const而言[1]:
第一、必須在宣告時指定初始值,而且不能再變更。
第二、若以const宣告參考型別,將侷限使用在string與null。
第三、以const宣告的變數,可以使用在使用const宣告的運算式中。
就readonly[2]而言:
第一、透過readonly修飾的變數,僅可在宣告時初始化。
第二、也可以在沒有參數的建構函式中初始化。
第三、倘若透過建構函式的參數初始化,將會取得預設值,而非建構函式的參數值。
第四、一個類別的實例的成員,若被readonly修飾,可以透過建構函式初始化。
第五、一個類別的static成員,若被readonly修飾,可以透過同一個類別的static建構函式初始化。
第六、前述第四點與第五點中,建構函式的參數皆可視為被out與ref修飾的參數。
就static[3][4]而言:
第一、static宣告的成員隸屬類別本身,而非特定物件。
第二、static可以選高的對象包含:classes、fields、methods、properties、operators、events與constructors,。但是不包含indexers、destructors或者類別以外的types。
第三、static宣告的類別僅能包含static宣告的方法。
第四、static宣告的成員必須透過類別(而非物件)才能存取。
第五、一個類別中,就static宣告的欄位而言,無論同一個類別產生幾個物件,皆共用同一個欄位。
第六、無法使用this參照static宣告的屬性或者方法的存取修飾子。
第七、當使用static宣告一個類別,則此一類別的所有成員都視同使用static宣告。
第八、無論有無使用static宣告類別,類別皆可以擁有使用static宣告的constructor。
第九、static constructor被呼叫的時間點落在程式啟動後,以及所屬的類別初始化或者被第一次參考引用之前。
第十、static宣告的類別一旦被引用之後,就會一直停留在記憶體中,與所屬的應用程式相伴。
第十一、透過Singleton Desgin Pattern,可以限制一個未被static宣告的類別僅能產生一個實例。
第十二、static class的四大特徵依序是1、僅包含static members。2、不能被初始化。3、不能被繼承(Sealed)。4、不能包含Instance Constructor。
第十三、使用static class的優點在於編譯器可以確保不會出現static class的instance。
第十四、static class不能繼承Object以外的class(They cannot inherit from any class except Objec),否則在編輯時期將會出現錯誤訊息:An object reference is required for the non-static field, method, or property.
第十五、倘若non-static class擁有一個static memeber,因此必須進行一個non-trivial initialization,則此一non-static class必須定義一個static constructor。
第十六、static method和static property不能存取本身所屬的類別的non-static field和event。
第十七、static method和static property不能存取任何一個物件的instance variable,除非明確透過method的參數傳遞。
第十八、一般經典的做法是在class中包含static member,而不是將整個class宣告成為static。原因有二:其一,限定初始化的物件的數量。其二,讓同一個class的眾多instance共享一個static member。
第十九、Static methods可以overload,但是不能overriden,否則在編譯時期,將會出現錯誤訊息:A static member cannot be marked as override, virtual, or abstract.
第廿、雖然一個field不能同時使用static與const宣告,但是const的行為與static相同,所以也可以直接透過class存取,倘若透過instance存取,將會在編輯時期出現錯誤訊息:Member cannot be accessed with an instance reference; qualify it with a type name instead.
第廿一、C#不支援使用static宣告區域變數。
第廿二、static memeber則是在本身第一次被使用前或者(唯一僅有的)static constructor被呼叫之前進行initialize。
第廿三、static field可以在宣告時直接initialize,或者利用class被載入時,透過static constructor進行initialize。
第廿四、在MSIL中,呼叫static method會對應至一個call instruction,至於呼叫instance method則會對應至一個callvirt instruction,並且檢查null object reference。但是二者效能並無顯著差異。
就static constructor[5]而言:
第一、功能有二:其一、initialize一個class中的static field。其二、initialize一個class中的static memeber。
第二、被自動呼叫的時間點有二:其一、class的instance被創造之前。其二、class的static member被參考之前。
第三、不接受存取修飾子,也不接收參數。
第四、不能被直接呼叫。
第五、當static constructor開始執行時,使用者沒有掌控權。
第六、static constructor的實際應用情境,包含將記錄寫入log檔。
第七、設計一個類別包裹unmanaged code,而且此一unmanaged code包含LoadLibrary Method時,static constructor將會相當有用[6]。
第八、一旦static constructor拋出一個exception,.Net Runtime Envrionment將不會再度呼叫此一static constructor。在整個應用程式執行的期間,原因應該由此一static constructor進行initialize的type將會一直保持uninitialized的狀態。
資料來源:
[1]const (C# Reference)
https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
[2]readonly (C# Reference)
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
[3]static (C# Reference)
https://msdn.microsoft.com/en-us/library/98f28cdx.aspx
[4]Static Classes and Static Class Members (C# Programming Guide)
https://msdn.microsoft.com/en-us/library/79b3xss3.aspx
[5]Static Constructors (C# Programming Guide)
https://msdn.microsoft.com/en-us/library/k9x6w0hc.aspx
[6]C# static constructors are called on demand, not at startup
http://blogs.msdn.com/b/oldnewthing/archive/2007/08/15/4392538.aspx