標籤:style blog color 使用 資料 問題 代碼 div
前沿:
欄位(field)是一種資料成員,其中容納了一個實值型別的執行個體或者一個參考型別的引用。
本文:
CLR支援類型(靜態)欄位和執行個體(非靜態)欄位。對於類型欄位,用於容納欄位資料的動態記憶體是在類型對象中分配的,而類型對象是在類型記載到一個AppDomain時建立的。那麼,什麼時候要將類型載入到一個AppDomain中呢?這通常是在引用了該類型的任何方法首次進行JIT編譯的時候。對於執行個體欄位,用於容納欄位資料的記憶體則是在構造類型的一個執行個體時分配的。
由於欄位儲存在動態記憶體中,所以他們的值在運行時才能擷取。欄位還解決了常量存在的版本控制問題。此外,欄位可以是任何資料類型,不必像常量那樣僅僅局限於編譯器內建的基元類型。那什麼是基元類型呢(int 、unit等等)?
基元類型:編譯器直接支援的資料類型。如果沒有基元類型,我們在聲明一個整數的時候應該是這樣子的
Int32 a=new Int32;
幸運的是有了基元類型,我們可以直接用下面的方法,也就是我們在編程的時候經常用到的:
int a=0;
再比如string和String,剛開始我對這兩個類型很困惑,到底什麼時候用哪一個呢,但是看了基元類型的講解,你就會明白,由於C#的string直接映射到String(FCL類型),所以兩者沒有區別,都可以使用。
CLR支援readonly欄位和read、write欄位。大多數欄位都是read和write欄位,這意味著在代碼執行過程中,欄位值可以多次改變。但是readonly欄位只能在一個構造器方法中寫入。(這個構造器方法只能調用一次,也就是對象首次被建立時),編譯器和驗證機制確保readonly欄位不會被構造器以外的方法寫入。但是可以利用反射來修改。
現在我們使用一個靜態readonly欄位來修正版本控制問題:
1 public sealed class someType2 {3 public static readonly int MaxList=50; 4 }
這是唯一需要修改的,應用程式的代碼不必修改。但是們為了觀察新的行為,必須重建他,當應用程式的Main方法運行時,CLR將載入到DLL程式集,並從分配給他的動態記憶體中提取MaxList欄位的值50.
假設DLL程式集的開發人員將50改為100,並重建程式集。當應用程式代碼重新執行時,他將自動提取欄位的新值100,在這種情況下,程式不需要重建,他可以直接運行。要注意的是,當前假定的是DLL程式集的新版本沒有進行強命名。
下面這個示範了如何定義一個與類型本身關聯的readonly靜態欄位和讀寫欄位。另外還定義了read/write靜態欄位。
class ServiceLocator { //靜態唯讀欄位,在運行時對這個類進行初始化時,他的值被存到記憶體中 public static readonly Random random = new Random(); private static int numberwrites = 0; public readonly string PathName = "Unity"; private FileStream fs; public ServiceLocator(string pathname) { //在構造器中可以修改唯讀欄位 this.PathName = pathname; } public string Do() { numberwrites += 1; return PathName; } }
在上述代碼中,許多欄位都是內聯初始化的(就是直接在代碼中直接賦值來初始化,而不是通過建構函式),C#允許使用這種方法來初始化類的常量、讀寫欄位、唯讀欄位。C#實際上是在建構函式中對欄位進行初始化的,欄位的內聯初始化只是一種文法上的簡化。
注意,當某個欄位是參考型別,並且該欄位被聲明為唯讀時,那麼不可改變的是引用本身,而不是引用的對象(也就是分配在堆中的值)。
public static readonly char[] Inva = new char[] { ‘a‘,‘B‘,‘C‘}; public void Test() { Inva[0]=‘v‘;//我們可以改變引用的對象,也就是改變引用指向的地址 Inva = new char[] { ‘x‘,‘y‘,‘z‘};//無法改變引用本身 }