1. 程式人生 > >程式設計結構(C#)

程式設計結構(C#)

正文

 

值型別和引用型別

值型別派生自System.ValueType,分配在棧上,不能被繼承,變數預設按值傳遞,當它們超出定義的作用域時被回收。

引用型別分配在託管堆上,變數指向例項所佔的記憶體地址,變數預設按引用傳遞(變數的地址傳入被呼叫的函式),託管堆被垃圾回收時變數消亡。

 

傳值與傳址

按值傳遞值型別,被呼叫者不能改變引數值;按引用傳遞值型別,可以改變引數值。

如果按值傳遞引用型別,被呼叫者可能改變物件的狀態資料的值,但不能改變所引用的物件,即不能讓物件指向另外一個物件。

如果按引用傳遞引用型別,被呼叫者可能改變物件的狀態資料的值和所引用的物件。

 

引數修飾符out和ref的區別

out: 呼叫方法之前不需要初始化,輸出引數由被呼叫的方法賦值,如果被呼叫的方法沒給輸出引數賦值,會出現編譯錯誤。

ref: 呼叫者賦初值,並且可以由被呼叫方法(可選地)重新賦值。

 

Internal和protected作用範圍

Internal: 只能在包含它的程式集中訪問該方法

Protected: 只有派生的型別和該類本身能訪問該方法。

Protected internal: 只能在包含它的程式集,和派生類的程式碼中訪問。

 

Using關鍵字

Using關鍵字用來:確保在物件引用超出作用域時,在實現了IDisposable介面的物件上自動呼叫Dispose()方法,實現資源回收。

 

靜態建構函式

靜態建構函式適用於初始化在編譯時未知的靜態資料值,例如,需要從外部檔案/資料庫讀取或生成隨機數等。一個類只能定義一個靜態建構函式,靜態建構函式只執行一次,靜態建構函式的執行優先於任何例項級別的建構函式。

 

垃圾回收

在使用.NET進行託管程式設計時,不需要對託管堆進行直接操作。如果託管堆沒有足夠的記憶體來分配請求的物件,GC就會進行垃圾回收。

重寫Finialize()的唯一原因是,C#類通過PInvoke或COM互操作性使用了非託管資源(如原始的作業系統檔案控制代碼,資料庫連線等)。

Finialize方法是保證垃圾回收時清除非託管資源。但對於資料庫和檔案控制代碼等非常寶貴的資源,應該儘快釋放。除了重寫Finialize()方法之外,可以實現IDisposable介面,它定義的Dispose方法可以由使用者手工呼叫。

 

物件的代

垃圾回收時,CLR會試圖尋找不可到達的物件,它不會逐個檢查託管堆上的每一個物件。為了優化這個過程,堆上的每一個物件都屬於某個代:

第0代:從沒有標記為回收的新分配的物件

第1代:在上一次垃圾回收中沒有被回收的物件

第2代:在一次以上的垃圾回收後仍然沒有被回收的物件

垃圾回收器檢查和處理所有的第0代物件,如果獲得足夠的空閒記憶體,就不用繼續檢查第1代和第2代的物件,同時沒有被回收的物件被提升到第1代。

 

GAC

Global Assembly Cache是全域性程式集快取。大多數共享程式集都安裝在這個快取中,其中也安裝了一些私有程式集。如果私有程式集使用本機影象生成器(Ngen.exe)編譯為本機程式碼,也會儲存在這個快取中。

內部影象生成器(native image generator)Ngen.exe,可以在安裝期間把IL程式碼編譯為本機程式碼,這樣程式啟動更快。

 

 

正式的處置模式

    public class MyResourceWrapper : IDisposable {

        private bool disposed = false;

 

        public void Dispose() {

            CleanUp(true);

            GC.SuppressFinalize(this);//跳過終結

        }

 

        private void CleanUp(bool disposing) {

            if (!this.disposed) {

                if (disposing) {

                    //釋放託管的資源(在包含的可處置物件上呼叫Dispose)

                }

                //在這裡釋放非託管的資源

            }

            disposed = true;

        }

 

        ~MyResourceWrapper() {

            CleanUp(false);

        }

    }